Forum Discussion

PowerShellDon_1's avatar
PowerShellDon_1
Icon for Nimbostratus rankNimbostratus
Dec 04, 2015

iRule - Adding a cookie based on Geo-IP , without breaking everything

Hi all, First post on DevCentral, i've done a handful of iRules but not great at them.

I have a case where we have a website with multiple language/country versions. I have been asked to be able to change a resource on the site based upon the clients US State. At the moment, we are just targeting Florida. The logic on the server side is setup and works, so if cookie "uslocation" has value "florida" the logo changes.

The problem is, the logo wont change without me adding the cookie to the HTTP_RESPONSE And i suspect i'm not doing the HTTP_RESPONSE correctly, because it fails to load everything that isnt in the /usa/ path, and if the cookie isn't present, the connection is dropped.


when HTTP_REQUEST {

if { [string tolower [HTTP::host]] equals "mywebsite.com" && [HTTP::path] eq "/usa" }{

        Parse the client IP from the header supplied
      set client_ip [HTTP::header value "X-Forwarded-For"]
        log local0. " Staging - XFF ... incoming connection from $client_ip "

       if { $client_ip eq "" }{
             The header was empty/did not exist, so use the actual client IP
               log local0. "Staging - XFF Header was empty so using actual IP - $client_ip"
            set client_ip [IP::client_addr]
         }
       
    set state [string tolower [whereis $client_ip state]]
    log local0. " Staging - incoming connection from $client_ip detected state as $state"
    if { $state eq "florida" } {
        log local0. " Staging -  .. $state.. "
        set cookie_insertion 1
        HTTP::cookie insert name "uslocation" value $state path "/usa"  domain "mywebsite.com" }
  log local0. "Cookies = [HTTP::cookie uslocation] "

      }
 else {
        pool POOL-STAGING-HTTP
  }
}
when HTTP_RESPONSE {

if { $cookie_insertion > 0 }{
        log local0. " RESPONSE - Adding cookie to response Staging - ... $state.. "
        HTTP::cookie insert name "uslocation" value $state path "/usa"  domain "mywebsite.com" 
       log local0. "RESPONSE - Cookies = [HTTP::cookie uslocation] " }
     }

Any help would be hugely appreciated

  • Are your URLs prefixed with "/usa" or just "/usa"? You may want to use starts_with instead of equals in your if statement if that's the case.

    Also, I would use

    HTTP::cookie replace
    instead of
    insert
    because it will replace an existing cookie and only insert it if there isn't already one. And I don't think you'd need the domain and path on the request insert.

    I think you have a syntax error in your

    HTTP_RESPONSE
    event too. If the variable is not initialized to anything, then in when you check it, it will be undefined and a TCL error will occur. Because of that, you'll need to use the
    [info exists varname]
    . That may help.

    Here's an updated iRule to try

    when HTTP_REQUEST {
        if { [string tolower "[HTTP::host][HTTP::uri]"] starts_with "mywebsite.com/usa" } {            
             Parse the client IP from the header supplied
            if { [HTTP::header exists "X-Forwarded-For"] } {
                log local0. " Staging - XFF ... incoming connection from $client_ip"
                set client_ip [HTTP::header value "X-Forwarded-For"]
            } else {
                log local0. "Staging - XFF Header was empty so using actual IP - $client_ip"
                set client_ip [IP::client_addr]
            }
    
            set state [string tolower [whereis $client_ip state]]
            log local0. " Staging - incoming connection from $client_ip detected state as $state"
            if { $state eq "florida" } {
                log local0. " Staging -  .. $state.. "
                set cookie_insertion 1
    
                 I would use 'replace' instead of insert so it'll only keep a single cookie instead of adding an additional one
                HTTP::cookie replace name "uslocation" value $state 
            }
    
            log local0. "Cookies = [HTTP::cookie uslocation] "
        } else {
            pool POOL-STAGING-HTTP
        }
    }
    
    when HTTP_RESPONSE {
        if { [info exists cookie_insertion] && $cookie_insertion > 0 }{
            log local0. " RESPONSE - Adding cookie to response Staging - ... $state.. "
            HTTP::cookie insert name "uslocation" value $state path "/usa"  domain "mywebsite.com" 
            log local0. "RESPONSE - Cookies = [HTTP::cookie uslocation] " }
        }
    }