Forum Discussion

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

irule to redirect info.blah.edu catches all paths, not just the three defined

Match subdomain.domain, with a "/", b_path, c_path, d_path; Then A/B load balance 60/40 percent ratio.

 

Created 12/11/2012 Christian Henderson

 

Last edited 12/11/12

 

when RULE_INIT {

 

log local0. "initializing ... "

 

set static::debug 1

 

Host header variables for sub-domain and domain.

 

set static::a_sub "degrees"

 

set static::b_sub "onlinedegrees"

 

set static::c_sub "info"

 

set static::domain "blah.edu"

 

Path variables.

 

set static::b_path "\?*"

 

set static::c_path "index.htm"

 

set static::d_path "degrees"

 

 

 

Current count variable.

 

set static::current 0

 

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

 

set static::ratio 6

 

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\]" }

 

Only catch requests that come in with the proper host header

 

if { [string tolower [HTTP::host]] equals "$static::c_sub.$static::domain" } {

 

Only catch clients that come in through the URI path static::a_path, static::b_site, or static::c_path

 

if { [string tolower [HTTP::path]] equals "/" || [string tolower [HTTP::uri]] matches_glob "/$static::b_path" || [string tolower [HTTP::uri]] starts_with "/$static::c_path" || [string tolower [HTTP::uri]] starts_with "/$static::d_path" } {

 

Check for < current for 60% of traffic.

 

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

 

Redirect traffic to A subdomain

 

if { $static::debug } { log local0. "redirect FROM [HTTP::uri] TO " }

 

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

 

Increment the counter

 

incr static::current

 

log local0. "A count is ${static::current} with ratio ${static::ratio}"

 

} else {

 

Redirect traffic to B subdomain for 40% requests

 

if { $static::current < $static::max } {

 

Redirect traffic to B subdomain

 

if { $static::debug } { log local0. "redirect FROM [HTTP::uri] TO " }

 

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

 

if { $static::debug > 1 } { log local0. "round robin is $static::round_robin" }

 

Increment the counter

 

incr static::current

 

log local0. "B count is ${static::current} with max ${static::max}"

 

} else {

 

If current count is 10, reset count to 0 and redirect traffic to A subdomain

 

if { $static::current >= $static::max } {

 

set static::current 0

 

log local0. "Reset current variable to ${static::current} "

 

if { $static::debug } { log local0. "redirect FROM [HTTP::uri] TO " }

 

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

 

TCP::close

 

event HTTP_REQUEST disable

 

}

 

}

 

}

 

}

 

}

 

}

 

7 Replies

  • Hi Christian,

     

     

    Can you add the client IP:port to the log lines, enable debug, retest and reply with the logs from /var/log/ltm for a failure?

     

     

    Replace:

     

    log local0. "

     

     

    with:

     

    log local0. "[IP::client_addr]:[TCP::client_port]:

     

     

    Thanks, Aaron
  • Here are the logs. As you can see info.blah.edu, info.blah.edu/degres, and info.blah.edu/index.htm match as expected, and the 60/40 A/B load balancing also works as expected, but the irule is also matching anything past info.blah.edu, such as info.blah.edu/fake.htm, or info.blah.edu/mba.htm which is not in the match criteria.

     

     

    tail -f /var/log/ltm | grep -v member

     

    Jan 7 07:15:30 bpeca03-f501dev err mcpd[3534]: 01020066:3: The requested rule (irule_info.blah_301_controller) already exists in partition Dev.

     

    Jan 7 07:15:30 tmm info tmm[5250]: Rule irule_info.blah_301_controller : initializing ...

     

    Jan 7 07:15:30 tmm1 info tmm1[5251]: Rule irule_info.blah_301_controller : initializing ...

     

    Jan 7 07:16:39 tmm info tmm[5250]: Rule irule_info.blah_301_controller : redirect FROM 10.50.8.12:63030 /mba.htm TO http://degrees.blah.edu/

     

    Jan 7 07:16:39 tmm info tmm[5250]: Rule irule_info.blah_301_controller : A count is 1 with ratio 6

     

    Jan 7 07:16:54 tmm info tmm[5250]: Rule irule_info.blah_301_controller : redirect FROM 10.50.8.12:63030 /blah.htm TO http://degrees.blah.edu/

     

    Jan 7 07:16:54 tmm info tmm[5250]: Rule irule_info.blah_301_controller : A count is 2 with ratio 6

     

    Jan 7 07:17:14 tmm info tmm[5250]: Rule irule_info.blah_301_controller : redirect FROM 10.50.8.12:63030 /degrees TO http://degrees.blah.edu/

     

    Jan 7 07:17:14 tmm info tmm[5250]: Rule irule_info.blah_301_controller : A count is 3 with ratio 6

     

    Jan 7 07:17:34 tmm info tmm[5250]: Rule irule_info.blah_301_controller : redirect FROM 10.50.8.12:63030 /fake.htm TO http://degrees.blah.edu/

     

    Jan 7 07:17:34 tmm info tmm[5250]: Rule irule_info.blah_301_controller : A count is 4 with ratio 6

     

    Jan 7 07:18:09 tmm info tmm[5250]: Rule irule_info.blah_301_controller : redirect FROM 10.50.8.12:63030 /degrees TO http://degrees.blah.edu/

     

    Jan 7 07:18:09 tmm info tmm[5250]: Rule irule_info.blah_301_controller : A count is 5 with ratio 6

     

    Jan 7 07:18:15 tmm info tmm[5250]: Rule irule_info.blah_301_controller : redirect FROM 10.50.8.12:63030 / TO http://degrees.blah.edu/

     

    Jan 7 07:18:15 tmm info tmm[5250]: Rule irule_info.blah_301_controller : A count is 6 with ratio 6

     

    Jan 7 07:18:23 tmm info tmm[5250]: Rule irule_info.blah_301_controller : redirect FROM 10.50.8.12:63030 /blah.htm TO http://onlinedegrees.blah.edu/

     

    Jan 7 07:18:23 tmm info tmm[5250]: Rule irule_info.blah_301_controller : B count is 7 with max 10

     

     

  • Can you change the matches_glob to starts_with and retest?

     

     

    Thanks, Aaron
  • So switching from matches_glob to starts_with fixes it, but then creates another issue. Then when I try to match a path with info.blah.edu/?loadsflkjaskdfj, it doesn't match the info.blah.edu/?* (which is why I tried using matches_glob. Any idea how to catch those without breaking the rest of the code? Thanks!
  • If you use starts_with info.blah.edu/? should match info.blah.edu/?adsfasdf. Can you remove the * from the variable value you're testing with?

     

     

    Aaron
  • Removing the * fixed it! I don't know why I didn't think of that before.. starts_with is the same as \?* anyways.. Thanks for your help! On a side note (but this isn't a deal breaker at all), how would I get this working using a switch statement instead of an if? I tried using a switch statement to clean up the code, but I couldn't get it to work (see below). No worries at all if it's too much work to figure out, I'm just trying to get away from if statements and move to switch to reduce code. I tried the following, but the switch statements don't seem to match correctly.. Thanks for your help!

     

     

    Match subdomain.domain, with a path "/", b_path, c_path; Then A/B load balance 60/40 percent ratio.

     

    Created 12/11/2012 Christian Henderson

     

    Last edited 12/11/12

     

     

    when RULE_INIT {

     

    log local0. "initializing ... "

     

    set static::debug 1

     

     

    Host header variables for sub-domain and domain.

     

    set static::a_sub "degrees"

     

    set static::b_sub "onlinedegrees"

     

    set static::c_sub "info"

     

    set static::domain "blah.edu"

     

     

    Path variables.

     

    set static::b_path "\?"

     

    set static::c_path "index.htm"

     

    set static::d_path "degrees"

     

     

     

    Current count variable.

     

    set static::current 0

     

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

     

    set static::ratio 6

     

    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\]" }

     

     

    Only catch requests that come in with the proper host header, and matching /, b_path,c_path, or d_path.

     

    if { [string tolower [HTTP::host]] equals "$static::c_sub.$static::domain" } {

     

    Only catch clients that come in through the URI path static::a_path, static::b_path, or static::c_path

     

    switch -glob [string tolower [HTTP::uri]] "/" -

     

    "/$static::b_path*" -

     

    "/$static::c_path*" -

     

    "/$static::d_path*" {

     

    Check for < current for 60% of traffic.

     

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

     

    Redirect traffic to A subdomain

     

    if { $static::debug } { log local0. "redirect FROM [HTTP::uri] TO http://${static::a_sub}.${static::domain}/$new_query" }

     

    HTTP::respond 301 Location "http://${static::a_sub}.${static::domain}/$new_query" "Cache-Control" "no-cache, must-revalidate"

     

    Increment the counter

     

    incr static::current

     

    log local0. "A count is ${static::current} with ratio ${static::ratio}"

     

    } else {

     

    Redirect traffic to B subdomain for 40% requests

     

    if { $static::current < $static::max } {

     

    Redirect traffic to B subdomain

     

    if { $static::debug } { log local0. "redirect FROM [HTTP::uri] TO http://${static::b_sub}.${static::domain}/$new_query" }

     

    HTTP::respond 301 Location "http://${static::b_sub}.${static::domain}/$new_query" "Cache-Control" "no-cache, must-revalidate"

     

    if { $static::debug > 1 } { log local0. "round robin is $static::round_robin" }

     

    Increment the counter

     

    incr static::current

     

    log local0. "B count is ${static::current} with max ${static::max}"

     

    } else {

     

    If current count is 10, reset count to 0 and redirect traffic to A subdomain

     

    if { $static::current >= $static::max } {

     

    set static::current 0

     

    log local0. "Reset current variable to ${static::current} "

     

    if { $static::debug } { log local0. "redirect FROM [HTTP::uri] TO http://${static::a_sub}.${static::domain}/$new_query" }

     

    HTTP::respond 301 Location "http://${static::a_sub}.${static::domain}/$new_query" "Cache-Control" "no-cache, must-revalidate"

     

    TCP::close

     

    event HTTP_REQUEST disable

     

    }

     

    }

     

    }

     

    }

     

    }

     

    }

     

     

  • Tcl requires special formatting to use variables as the cases in a switch statement:

     

     

    See the two examples on the DC wiki page for switch for details:

     

     

    https://devcentral.f5.com/wiki/iRules.switch.ashx

     

    Here are two examples with slightly different syntax for how to use variables as switch cases. Both examples log "matched starts_with $case2: test2".

     

     

    Aaron