Forum Discussion

Tadaoki_237078's avatar
Tadaoki_237078
Icon for Nimbostratus rankNimbostratus
Dec 17, 2015

iRules: Pool selection by URI and cookies

Hello everyone

I want to make an iRule which;

1) Select a pool by URI during first http request 2) For the subsequent requests for css and graphic files(with URI different than the first request), load balance by cookie.

What I got so far:

when HTTP_REQUEST {
   log -noname local0. "HTTP_REQUEST URI: [HTTP::uri]"

   switch -glob [substr [ HTTP::uri ] 1]
   {
     "foo/*" { pool pool_foo
      The server have all content in / 
      HTTP::uri [string map {"/foo/" "/"} [HTTP::uri]]
      log -noname local0. "Selected pool_foo by URI" 
      }

     "bar/*" { 
     pool pool_bar
     HTTP::uri [string map {"/bar/" "/"} [HTTP::uri]]
     log -noname local0. "Selected pool_bar by URI"
     }

 default {
        switch -glob [HTTP::cookie names]
        {
        "*pool_foo" { pool pool_foo
        log -noname local0. "Selected pool_foo by cookie"
        }

            "*pool_bar" { pool pool_bar
            log -noname local0. "Selected pool_bar by cookie"
            }

    default { 
    log -noname local0. "NO MATCH  by cookie.."
    }
        }
      }
   }
}

The problem with this approach is that when the client(browser) has multiple(or all) cookies, the default part of the switch will always load balance to pool_foo.

I have two ideas to go about this problem:

1)Delete cookies so that I only have the one cookie I need at all times.

2)Make a variable to determine the "current" cookie across events.

Any help is appreciated. Thank you.

-Kai

2 Replies

  • Hi Kai,

    there are at least two aspects to consider:

    1) a URI will start with a slash

    /
    character. So the validation has to match a string of i.e "/foo", "/foo*", "*foo"

    Without a literal slash or a wildcard as

    *
    in case you are using globbing you will not get a match.

    2) The function

    HTTP::cookie names
    returns a list. A list cannot be matched versus a jump table as used by the
    switch
    command.

    You want to use exact matches for an exact cookie name by using i.e.:

    foreach cookie_name [HTTP::cookie names] {
       switch $cookie_name {
           "foo_named_cookie" { 
               
               return
           }
           "bar_named_cookie" { 
               
               return
           }
       }
    }
    

    It will be important to use a

    return
    after running the action for a match to exit the evaluation.

    Thanks, Stephan

  • Hi Kai,

    instead of using

    [substr [ HTTP::uri ] 1]
    (aka. striping the first character) in combination with "foo/" you may want to use just
    [HTTP::uri]
    in combination with "/foo/". Both will work, but the later one will save you some CPU cycles.

    instead of using

    [string map {"/bar/" "/"} [HTTP::uri]]
    you may want to use
    [string range [HTTP::uri] 4 end]
    , where "4" represents the number of trailing chars to be removed. Again... both will work, but the later one will save some additional CPU cycles.

    The cookie based routing problem you're experincing, is almost impossible to fix using multiple independend cookie_names. I would recommend to change your cookie based routing logic to use an additional "cookie_name" for both subsites. The value of this cookie would then contain the needed routing (e.g. either "foo" or "bar"). The cookie could be insert by your backend servers or using an

    HTTP_RESPONSE
    iRule at the time the user visits the URI /foo or /bar. To move between the different subsites, you have to make sure the user visits the URI /foo or /bar initially, to get the new cookie value.

    Cheers, Kai