Forum Discussion

Brad_Baker's avatar
Oct 01, 2013

Directing traffic based on query parameter

We need the ability to direct traffic to a specific node on our LTM load balancers based on query parameter.

 

So for instance if I enter www.foo.com/some-article?s=web-server1 the request would get sent to web-server1, likewise if I were to access www.foo.com/myarticle.php?s=web-server2 the request would get sent to web-server2.

 

I found something very close here: https://devcentral.f5.com/wiki/iRules.Select_pool_member_based_on_HTTP_query_string_parameter.ashx

 

The issue is that this selects the 0th, 1st, 2nd, Nth pool member from the active members of a pool but we want to use the server name not member number. So for instance my member servers may be called web-server5, web-server6, web-server7, web-server8

 

Its un-intuitive to call member=1 and expect to get web server five. You'd expect if ?member=1 then you'd get web-server1 (even though web-server5 is the first in this pool.) Is there some way to call the node name specifically instead of the member number?

 

Thanks Brad

 

5 Replies

  • If you map the query string name to the pool member IP address this should be very easy using the 'pool member x.x.x.x' command syntax.

     

  • I'm not sure I am following. Are you suggesting we do http://somedomain/somepage?s=192.168.0.15?

     

    If so I'm afraid that's even less intuitive. I would really like this to be as simple as possible. What I'm really concerned with is asking colleagues to remember s=1 is really web-server5. Asking them to remember web-server5 is really 192.168.0.156 is even more cumbersome.

     

    If I'm misunderstanding though please let me know.

     

  • As Steve relates, you need some (unfortunately manual) approach to mapping the web server's name to a node address. This can usually be done with a string-based data group. Example:

    Data group (ex. my_webserver_dg):

    "web-server1" := "10.10.10.10 80"
    "web-server2" := "10.10.10.11 80"
    "web-server3" := "10.10.10.12 80"
    "web-server4" := "10.10.10.13 80"
    "web-server5" := "10.10.10.14 80"
    

    And then an iRule that looks for the query string and routes accordingly, otherwise uses standard persistence:

    when HTTP_REQUEST {
        if { [string tolower [HTTP::uri]] starts_with "/myarticle.php?s=" } {
            set webserver [URI::query [string tolower [HTTP::uri]] s]
            if { [class match $webserver equals my_webserver_dg] } {
                set nodelist [split [class -value match $webserver equals my_webserver_dg] " "]
                node [lindex $nodelist 0] [lindex $nodelist 1]
            }
        }
    }
    
  • Same datagroup. Slightly different iRule ([URI::query] does not work as expected in v10):

    when CLIENT_ACCEPTED {
        set default_pool [LB::server pool]
    }
    when HTTP_REQUEST {
        if {[class match -value [string tolower [URI::query [HTTP::uri] s]] eq dg_name_node] ne ""} {
            node [class match -value [string tolower [URI::query [HTTP::uri] s]] eq dg_name_node] 80
        }
    }
    when LB_FAILED {
        log local0. "Selected server [LB::server] did not respond. Re-selecting node from $default_pool"
        pool $default_pool
        LB::reselect
    }