Forum Discussion
direct traffic based on information from the XML request
Dear All,
I need a solution on IRULE for example to solve the following scenario:
I have 10 servers that will receive XML requests. the unique ID in each XML request will be a number such as:
965123239490
now I want to direct the traffic depends on the last digit on that number. So, the traffic in "if else" style will be as follow:
{ if request ends with digit 0 in the number --> send it to server 1 in case server 1 down --> send it to server 2 } if request ends with digit 1 in the number --> send it to server 2 in case server 2 down --> send it to server 3 } if request ends with digit 2 in the number --> send it to server 3 in case server 3 down --> send it to server 4 }
etc.....
appreciate your support on how to get this down using F5 LB.
Thanks in advance. Mohamed.
27 Replies
- Kevin_Stewart
Employee
If you can send an example of the XML request that'd help in building an actual iRule. Otherwise,
when HTTP_REQUEST { some function to parse out the digits from the xml request switch -glob $digit { "*0" { if { [LB::status node 10.10.10.1] eq "up" } { node 10.10.10.1 80 } else { node 10.10.10.2 80 } } "*1" { if { [LB::status node 10.10.10.2] eq "up" } { node 10.10.10.2 80 } else { node 10.10.10.3 80 } } "*2" { if { [LB::status node 10.10.10.3] eq "up" } { node 10.10.10.3 80 } else { node 10.10.10.4 80 } } default { send to a default pool or node } } }Of course this doesn't deal with any type of persistence and what happens if the failover node is also down.
- Kevin_Stewart
Employee
Okay, well there's an XML xpath way to do this with the XML_CONTENT_BASED_ROUTING event and an XML profile, but for such a small set of data that's probably more complicated than a single string parse.
when HTTP_REQUEST { if { [HTTP::header Content-Type] contains "xml" } { HTTP::collect [HTTP::header Content-Length] } } when HTTP_REQUEST_DATA { set number [string trim [findstr [HTTP::payload] "" 8 ""]] enable for testing log local0. "number = $number" now that you have the number you can add the switch code to find the last digit }I'm making an assumption of course that the XML request has a Content-Type header with the word "xml" in it, and I'm also not accounting for what might happen if the request isn't xml, but I hope this gets you going in the right direction.
- Kevin_Stewart
Employee
Almost. You're assigning your XML value to the number variable, so the switch statement should reflect that:
switch -glob $number - Al-Mutlaq_21911
Nimbostratus
Hi Kevin,
i tried to apply the following IRULE: when HTTP_REQUEST { if { [HTTP::header Content-Type] contains "xml" } { HTTP::collect [HTTP::header Content-Length] }
when HTTP_REQUEST_DATA { set msisdn [string trim [findstr [HTTP::payload] "" 8 ""]]
enable for testing log local0. "msisdn = $msisdn" }when HTTP_REQUEST { some function to parse out the digits from the xml request
switch -glob $msisdn { "*0" { if { [LB::status node 10.10.10.1] eq "up" } { node 172.24.248.85 8580 } else { node 172.24.248.85 8680 } } "*1" { if { [LB::status node 10.10.10.2] eq "up" } { node 172.24.248.85 8580 } else { node 172.24.248.85 8680 } } default { send to a default pool or node } } }}
but i got an error: 01070151:3: Rule [UCIP_MSISDN] error: line 6: [command is not valid in the current scope] [when HTTP_REQUEST { set msisdn [string trim [findstr [HTTP::payload] "" 8 ""]]
enable for testing log local0. "msisdn = $msisdn" }] line 12: [command is not valid in the current scope] [when HTTP_REQUEST { some function to parse out the digits from the xml request
switch -glob $msisdn { "0" { if { [LB::status node 10.10.10.1] eq "up" } { node 172.24.248.85 8580 } else { node 172.24.248.85 8680 } } "1" { if { [LB::status node 10.10.10.2] eq "up" } { node 172.24.248.85 8580 } else { node 172.24.248.85 8680 } } default { send to a default pool or node } } }]
appreciate your feedback.
- Al-Mutlaq_21911
Nimbostratus
Hi, appreciate your help please
- Stanislas_Piro2
Cumulonimbus
Hi Mohammed,
All the XML decision must be done in HTTP_REQUEST_DATA event.
HTTP_REQUEST { if { [HTTP::header Content-Type] contains "xml" } { HTTP::collect [HTTP::header Content-Length] } } when HTTP_REQUEST_DATA { set msisdn [string trim [findstr [HTTP::payload] "" 8 ""]] switch -glob $msisdn { "*0" { if { [LB::status node 10.10.10.1] eq "up" } { node 172.24.248.85 8580 } else { node 172.24.248.85 8680 } } "*1" { if { [LB::status node 10.10.10.2] eq "up" } { node 172.24.248.85 8580 } else { node 172.24.248.85 8680 } } default { send to a default pool or node } } } - Stanislas_Piro2
Cumulonimbus
In your irule, I can see that all pool members are hosted on the same address... so the node status is useless... you must use a pool member status instead.
I changed the irule with right configuration.
The first event is to store the default pool name in the variable
default_poolTo use it, all of services must be in the same pool. if it is wrong, you must replace in the condition
and member assignment[LB::status pool $default_pool member 172.24.248.85 8580]
$default_pool with the pool with the good monitor.pool $default_pool member 172.24.248.85 8580when CLIENT_ACCEPTED { set default_pool [LB::server pool] } HTTP_REQUEST { if { [HTTP::header Content-Type] contains "xml" } { HTTP::collect [HTTP::header Content-Length] } } when HTTP_REQUEST_DATA { set msisdn [string trim [findstr [HTTP::payload] "" 8 ""]] switch -glob $msisdn { "*0" { if { [LB::status pool $default_pool member 172.24.248.85 8580] eq "up" } { pool $default_pool member 172.24.248.85 8580 } else { pool $default_pool member 172.24.248.85 8680 } } "*1" { if { [LB::status pool $default_pool member 172.24.248.85 8680] eq "up" } { pool $default_pool member 172.24.248.85 8580 } else { pool $default_pool member 172.24.248.85 8680 } } default { send to a default pool or node } } }Another solution is to create one pool per msisdn condition with two pool members and priority group activation.
the irule become:
HTTP_REQUEST { if { [HTTP::header Content-Type] contains "xml" } { HTTP::collect [HTTP::header Content-Length] } } when HTTP_REQUEST_DATA { set msisdn [string trim [findstr [HTTP::payload] "" 8 ""]] switch -glob $msisdn { "*0" { pool msisdn0 } "*1" { pool msisdn1 } default { send to a default pool or node } } } - Al-Mutlaq_21911
Nimbostratus
Hi,
thanks a lot for your support, what about if i have something different than XML, for example i have below sample request that i would like to balance it with the same concept:
GET /myPromo-?msisdn=96650283329&segmentation=1&language=en®ister=1&description=1&channel=iPad&grouptype=0&type=1&method=select&context=SCC HTTP/1.1 Accept: text/html, application/xhtml+xml, / Accept-Language: ar-SA User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0) Accept-Encoding: gzip, deflate Host: 172.24.248.85:8280 Connection: Keep-Alive
Thanks,
- Al-Mutlaq_21911
Nimbostratus
Hi,
appreciate your support. BR,
- Al-Mutlaq_21911
Nimbostratus
Hi,
i really need help on it please :)
BR
- Stanislas_Piro2
Cumulonimbus
Here the irule to do both XML and parameter parsing.
when CLIENT_ACCEPTED { set default_pool [LB::server pool] } HTTP_REQUEST { set msisdn [URI::decode [URI::query [HTTP::uri] msisdn]] if {[string length $msisdn] } { switch -glob $msisdn { "*0" { if { [LB::status pool $default_pool member 172.24.248.85 8580] eq "up" } { pool $default_pool member 172.24.248.85 8580 } else { pool $default_pool member 172.24.248.85 8680 } } "*1" { if { [LB::status pool $default_pool member 172.24.248.85 8680] eq "up" } { pool $default_pool member 172.24.248.85 8580 } else { pool $default_pool member 172.24.248.85 8680 } } default { send to a default pool or node } } } elseif { [HTTP::header Content-Type] contains "xml" } { HTTP::collect [HTTP::header Content-Length] } } when HTTP_REQUEST_DATA { set msisdn [string trim [findstr [HTTP::payload] "" 8 ""]] switch -glob $msisdn { "*0" { if { [LB::status pool $default_pool member 172.24.248.85 8580] eq "up" } { pool $default_pool member 172.24.248.85 8580 } else { pool $default_pool member 172.24.248.85 8680 } } "*1" { if { [LB::status pool $default_pool member 172.24.248.85 8680] eq "up" } { pool $default_pool member 172.24.248.85 8580 } else { pool $default_pool member 172.24.248.85 8680 } } default { send to a default pool or node } } }
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
