Forum Discussion
Brent_Sachnoff_
Nimbostratus
Oct 23, 2007Using switch with uri
I'm having some issues using the switch command and uri's. I believe the switch command is only for EQUALS to something for it to work properly which means this wouldn't work at all. Here is a sample:
when HTTP_REQUEST {
switch [HTTP::uri] {
"/search/" { pool search }
"/int_search/" { pool search }
"/pictures/" { node 10.4.43.1 80 }
"/" { HTTP::redirect "https://[HTTP::host]/IMT/LoginAction.go" }
default {
pool www
}
}
}
is there a way to "match" vs equal on the uri in a switch statement?
starts_with "/search" or starts_with "/int_search/"
Thanks!
Brent
11 Replies
- hoolio
Cirrostratus
You can use the -glob flag on switch to enable wildcards. By default, switch uses -exact to require exact matches. Here is an example:when HTTP_REQUEST { switch -glob [HTTP::uri] { "/search/*" { pool search } "*/int_search/" { pool search } "/pictures/" { node 10.4.43.1 80 } "/" { HTTP::redirect "https://[HTTP::host]/IMT/LoginAction.go" } default { pool www } } }
/search/* would match anything starting with /search/. */int_search/ would match anything ending with /int_search/. /pictures/ would match only requests to exactly that URI.
For details on switch options, check the TCL page (Click here). Note that the -nocase flag described in the TCL page is not enabled for iRules. If you want to perform a case insensitive comparison, set the URI to lower case using 'switch -glob [string tolower [HTTP::uri]]'.
Aaron - John_48565
Nimbostratus
Can this take the place of an if else irule? I want to use a wildcard so that anything after /virtualdir/default/* goes to Pool_1 and then anything after /virtualdir/second/* goes to Pool_2
when HTTP_REQUEST {
if { [HTTP::uri] contains "/virtualdir/default"}{pool Pool_1}
elseif
{[HTTP::uri] contains "/virtualdir/second/viewproducts" or [HTTP::uri] contains "/virtualdir/second/ordersummary" or [HTTP::uri] contains "/virtualdir/second/billing" or [HTTP::uri] contains "/virtualdir/second/paybypaypal"}{pool Pool_2}}
when HTTP_REQUEST {
switch -glob [HTTP::uri] {
"/virtualdir/second/*" { pool Pool_2 }
default {
pool Pool_1
}
}
} - Brent_Sachnoff_
Nimbostratus
jyimcse - Yes I believe that would work for you.
Hoolio - Thanks for the help. I found the -glob about an hour before you posted it. Just to verify, if my uri looks like this:
/search/testscript?didthat=/search/done
and my switch statement has this in it:
"/search/*" { pool search }
Will this cause 2 hits or just be a single hit?
Thanks again! - If you just put "/search/*" in the case for the switch, it will only hit the first part of the string as you don't have any wildcards before the first slash. But, if you used "*/search/*" it would hit both (at least I think a beginning wildcard will match on nothing...)
As for your mention of "2 hits", I'm not sure what you mean by that. The case comparison in the switch statement is a boolean operation (does it match the pattern or not). So, 1, 2 or 50 matches all will result in the containing code being executed once.
-Joe - Brent_Sachnoff_
Nimbostratus
I need to be able to make sure my match is coming from:
www.test.com/search/blah* vs coming from
www.test.com/thiscanbeanything/search/blah*
or even from
www.test.com/search/blah/newsearch/search/*
If those are my 3 possibilities then I need to make sure it only returns true on the top vs the next two and with the switch statement I can not seem to use starts_with.
Joe I meant hit = true. - hoolio
Cirrostratus
You can test this by using a test string and a switch statement in the RULE_INIT event:when RULE_INIT { set ::test_uri /search/blah log local0. "test string: $::test_uri" switch -glob $::test_uri { /search/blah* { log local0. "matched /search/blah*" } /search/blah/foo* { log local0. "matched /search/blah*" } /search/blah* { log local0. "matched /search/blah*" } default { log local0. "didn't match any"} } }
From the command line, you can run 'tail -f /var/log/ltm' to see the log statements.
If you want two different actions for /search/blah* and /search/blah/newsearch/search/*, you could either put *newsearch* before /search/blah* or make /search/blah* more specific so it doesn't match /search/blah/newsearch/search/*.
Aaron - Brent_Sachnoff_
Nimbostratus
Aaron that gave me my answer! If we take this a step further, by inserting a cookie based on which case was matched I could use this for persistance. The F5 is throwing an error with my choice:
switch -glob [HTTP::uri] {
"/cc/*" {
if { ![HTTP::cookie exists "cc"] } {
persist cookie insert name cc
}
pool www2
}
The above works fine but has create some issues so I tried to set the path too. I changed the persist cookie line to:
persist cookie insert name cc value 123456 path "/cc"
The F5 complains: [wrong args]. Even if I get rid of the path portion it still complains about the same thing. Is there another way to use this command or another method that I should be looking at?
Thanks for all the responses so far. It has allowed me to rewrite some pretty nasty looking iRules. - Brent_Sachnoff_
Nimbostratus
Any reason why my rules aren't spaced properly when I post here? I swear I put them in properly. - hoolio
Cirrostratus
You can use the \[code\] \[/code\] tags to preserve the spacing. In case that doesn't format as expected, it's [ code ] and [ /code ] without the spaces. Or you can click on the link to the right with the C on a page to have the tags inserted for you.
From the persist wiki page (Click here), it looks like the relevant persist options are:persist cookie [insert [] []
You can set the path on the cookie with HTTP::cookie (Click here😞HTTP::cookie path cc /cc
Aaron - hoolio
Cirrostratus
Actually, I'm not sure that setting the path in the HTTP_REQUEST event will work as the cookie hasn't been inserted yet. If you're able to test, and it doesn't work in HTTP_REQUEST, can you try setting the path in HTTP_RESPONSE?
To do so, you could set a path variable in the switch and then reference that in the HTTP_RESPONSE event:when HTTP_REQUEST { switch -glob [HTTP::uri] { /cc/* { set path cc do other things } rest of switch checks default { set path none do other things } } } when HTTP_RESPONSE { if {HTTP::cookie exists $path}{ HTTP::cookie path $path "/$path" } }
Aaron
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects