Forum Discussion

Christian_15126's avatar
Christian_15126
Icon for Nimbostratus rankNimbostratus
Jan 24, 2013

irule switch statement not matching header or paths

Marketing has hit me with another irule fun project. This is what they want me to accomplish:

 

They want 60/40 split load balancing between the following URL's:

 

 

-------------- 40% -------------------------- ------------>> -------------- 60% --------------------------

 

http://blah.domain.com/ba-business-admin.htm ---> http://bleeg.domain.com/baBusinessAdministration.htm

 

http://blah.domain.com/ba-psychology.htm ---> http://bleeg.domain.com/baPsychology.htm

 

http://blah.domain.com/ma-education.htm ---> http://bleeg.domain.com/maEducation.htm

 

http://blah.domain.com/ba-law-enforcement.htm ---> http://bleeg.domain.com/baLawEnforc...ration.htm

 

http://blah.domain.com/ba-journalis...cation.htm ---> http://bleeg.domain.com/baJournalis...cation.htm

 

 

ADDITIONAL REQUIREMENT:

 

 

Append a parameter to the URL to indicate percentage. For example: redirect=true

 

They also want any existing query variables passed through in addition to appending redirect=true. To avoid having a huge ass irule and five seperate irules for each 60/40 split, I've come up with. The irule passes the sanity check in notepad++ and irule editor, but when I try to hit blah.domain.com/anymatch, all I get is "new query string is \[$new_query\]". I tried turning on logging for the increment variable count and uri and redirect actions, but it seems like the irule doesn't even get there or doesn't successfully match the paths. Am I missing something fundamental here? I know how to make this work with straight if/else statements, but it will be really long and ugly, so I'm strying to 'switch' my brain (pun intended) into using switch instead of if/else statements wherever possible. Any help would be appreciated. CH

 

when RULE_INIT {

 

log local0. "initializing ... "

 

set static::debug 1

 

Host header variables for sub-domain and domain.

 

set static::a_sub "blah"

 

set static::b_sub "bleeg"

 

set static::domain "domain.com"

 

Path variables.

 

set static::a_Apath "ba-business-admin.htm"

 

set static::a_Bpath "baBusinessAdministration.htm"

 

set static::b_Apath "ba-psychology.htm"

 

set static::b_Bpath "baPsychology.htm"

 

set static::c_Apath "ma-education.htm"

 

set static::c_Bpath "maEducation.htm"

 

set static::d_Apath "ba-law-enforcement.htm"

 

set static::d_Bpath "baLawEnforcementAdministration.htm"

 

set static::e_Apath "ba-journalism-mass-communication.htm"

 

set static::e_Bpath "baJournalismMassCommunication.htm"

 

 

 

Marketing variable

 

set static::mktgvar "redirect=true"

 

Current count variable.

 

set static::current 0

 

1 in N requests will go to B subdomain - 6 for 60/40 ratio.

 

set static::ratio 4

 

Max value to reset count.

 

set static::max 10

 

}

 

when HTTP_REQUEST {

 

F5 doesn't put the question mark in the query string

 

if { [HTTP::query] equals "" } { set new_query "" }

 

else { set new_query "?[HTTP::query]" }

 

if { $static::debug == 1 } { log local0. "new query string is \[$new_query\]" }

 

switch -glob [string tolower [HTTP::header "$static::a_sub.$static::domain"]] {

 

"/$static::a_Apath*" {

 

if { "$static::current < $static::ratio" } {

 

incr static::current

 

HTTP::uri [string tolower "/${static::a_Apath}${new_query}${static::mktgvar}" ]

 

} elseif { "$static::current < $static::max" } {

 

incr static::current

 

HTTP::respond 301 Location "}" "Cache-Control" "no-cache, must-revalidate"}

 

}

 

"/$static::b_Apath*" {

 

if {"$static::current < $static::ratio" } {

 

incr static::current

 

HTTP::uri [string tolower "/${static::b_Apath}${new_query}${static::mktgvar}" ]

 

 

} elseif { "$static::current < $static::max" } {

 

incr static::current

 

HTTP::respond 301 Location "}" "Cache-Control" "no-cache, must-revalidate"}

 

}

 

"/$static::c_Apath*" {

 

if { "$static::current < $static::ratio" } {

 

incr static::current

 

HTTP::uri [string tolower "/${static::c_Apath}${new_query}${static::mktgvar}" ]

 

 

} elseif { "$static::current < $static::max" } {

 

incr static::current

 

HTTP::respond 301 Location "}" "Cache-Control" "no-cache, must-revalidate"}

 

}

 

"/$static::d_Apath*" {

 

if { "$static::current < $static::ratio" } {

 

incr static::current

 

HTTP::uri [string tolower "/${static::d_Apath}${new_query}${static::mktgvar}" ]

 

 

} elseif { "$static::current < $static::max" } {

 

incr static::current

 

HTTP::respond 301 Location "}" "Cache-Control" "no-cache, must-revalidate"}

 

}

 

"/$static::e_Apath*" {

 

if { "$static::current < $static::ratio" } {

 

incr static::current

 

HTTP::uri [string tolower "/${static::e_Apath}${new_query}${static::mktgvar}" ]

 

 

} elseif { "$static::current < $static::max" } {

 

incr static::current

 

HTTP::respond 301 Location "}" "Cache-Control" "no-cache, must-revalidate"}

 

}

 

 

default {

 

set static::ratio 0

 

TCP::close

 

event HTTP_REQUEST disable

 

}

 

}

 

}

 

 

 

 

 

 

 

  • switch -glob [string tolower [HTTP::header "$static::a_sub.$static::domain"]] {what string do you want to match? is it http host header (HTTP::host), path (HTTP::path) or uri (HTTP::uri)?

     

     

    incr static::currenti do not think you should alter static global variable value anyway.
  • With the following variables (leaving our the host and path variables to make is simple):

     

     

    current == 0

     

    ratio == 4

     

    max == 10

     

    mktvar == redirect=true

     

     

    I'm trying to match:

     

     

    HTTP:;host

     

    AND HTTP::path

     

    AND current < ratio

     

    APPEND TO PATH w/ HTTP::query AND mktgvar

     

    INCR current

     

    OR current < max

     

    301 REDIRECT w/ HTTP::query AND mktgvar

     

    INCR current

     

    (Rinse and repeat five times for five different paths and redirects)

     

    OR

     

    (To close the loop, reset the count to 0, close out the session. and the event)

     

    SET current == 0

     

    TCP close

     

    EVENT disable

     

     

    I know how to do it with just if/else statements, but it's uggly..
  • If the more variable item is the paths I'd suggest this kind of structure;

     

     

    1) An if on the host

     

    -2) A switch on the path

     

    --3) Further if statements on the rest

     

     

    It still won't be great but it should look a little better. If you need an example for 'switch' just say and I'll post one.
  • That would be great! I'm having issues getting my switch commands to read the variables to be matched in my irule.. They work fine with just if/else statements.
  • OK, here's a simple example. If you don't need the * wildcards, you can omit the -glob;

    
    when HTTP_REQUEST {
     switch -glob [string tolower [HTTP::host]] {
      If HTTP host contains abc or def, redirect to xyz.com
      "*abc*" -
      "*def*" { HTTP::redirect https://www.xyz.com/xyz }
      If HTTP host contains ghi, redirect to mno.com
      "*ghi*" { HTTP::redirect https://www.mno.com/mno }
      If HTTP host is none of the above, take the default action below
      default {
       HTTP::redirect "https://[HTTP::host][HTTP::uri]" }
     }
    }
    

    Sorry, no time to customise to your rule but hopefully this give you an idea.
  • What about if you need to use a switch to match variables for the host header or path? That's the part I'm stuck on. Thanks for your help!
  • This perhaps;

    
    when HTTP_REQUEST {
     switch -glob [string tolower $variable-name] {
      "*abc*" -
      "*def*" { HTTP::redirect https://www.xyz.com/xyz }
      "*ghi*" { HTTP::redirect https://www.mno.com/mno }
      default {
       HTTP::redirect "https://[HTTP::host][HTTP::uri]" }
     }
    }