Forum Discussion
Any way to shorten this switch case iRule?
Here is my iRule.
when HTTP_REQUEST {
switch -glob [string tolower [HTTP::path]] {
"/dir1" -
"/dir1/" {
HTTP::respond 301 Location "http://www.domain1.com"
}
"/dir1/dir2" -
"/dir1/dir2/" {
HTTP::respond 301 Location "http://www.domain2.com"
}
}
}
I thought of putting "dir1*" but it would interfere with my 2nd condition.
16 Replies
- Yann_Desmarest_
Nacreous
Hello,
The switch condition are taken in the order, so you can define a /dir1* but after /dir1/dir2* for example.
when HTTP_REQUEST { switch -glob [string tolower [HTTP::path]] { "/dir1/dir2*" { HTTP::respond 301 Location "http://www.domain2.com" } "/dir1*" { HTTP::respond 301 Location "http://www.domain1.com" } } }- ShinRyuX
Nimbostratus
Hello, That solution would work but this iRule is actually a simplified version of my current iRule where I have over 100 redirect links along with uri parameters extracted from original URL. I would have to re-order the conditions in ways to prevent any conflicts from occuring. Is there anything that can be done without re-arraging the order? I tried few things like putting "dir1?" or even "dir1[ ?]" but they dont satisfy both conditinos i want. Thank You - Yann_Desmarest_
Nacreous
What is the logic behind your redirect links ? Maybe, you can extract patterns from your request uri and change the Location value accordingly with a string map command - ShinRyuX
Nimbostratus
This is the full logic when HTTP_REQUEST { Extract URL parameters set urlPath "[string tolower [HTTP::path]]?" if {[string tolower [HTTP::uri]] contains "?"} { set newUri [string map -nocase [list $urlPath "?"] [HTTP::uri]] } else { set newUri "" } Redirection Logic case switch -glob [string tolower [HTTP::path]] { "/file1.html" { HTTP::respond 301 Location "http://www.newdomain.com/en-US/destination1$newUri" } "/dir1" - "/dir1/" { HTTP::respond 301 Location "http://www.newdomain.com/fr-FR/destination2$newUri" } "/dir1/dir2" - "/dir1/dir2/" { HTTP::respond 301 Location "http://www.newdomain.com/fr-FR/destination3$newUri" } "/dir1/dir2/dir3" - "/dir1/dir2/dir3/" { HTTP::respond 301 Location "http://www.newdomain.com/fr-FR/destination4$newUri" } ... } The list goes on but the logic remains the same.
Hello,
The switch condition are taken in the order, so you can define a /dir1* but after /dir1/dir2* for example.
when HTTP_REQUEST { switch -glob [string tolower [HTTP::path]] { "/dir1/dir2*" { HTTP::respond 301 Location "http://www.domain2.com" } "/dir1*" { HTTP::respond 301 Location "http://www.domain1.com" } } }- ShinRyuX
Nimbostratus
Hello, That solution would work but this iRule is actually a simplified version of my current iRule where I have over 100 redirect links along with uri parameters extracted from original URL. I would have to re-order the conditions in ways to prevent any conflicts from occuring. Is there anything that can be done without re-arraging the order? I tried few things like putting "dir1?" or even "dir1[ ?]" but they dont satisfy both conditinos i want. Thank You - What is the logic behind your redirect links ? Maybe, you can extract patterns from your request uri and change the Location value accordingly with a string map command
- ShinRyuX
Nimbostratus
This is the full logic when HTTP_REQUEST { Extract URL parameters set urlPath "[string tolower [HTTP::path]]?" if {[string tolower [HTTP::uri]] contains "?"} { set newUri [string map -nocase [list $urlPath "?"] [HTTP::uri]] } else { set newUri "" } Redirection Logic case switch -glob [string tolower [HTTP::path]] { "/file1.html" { HTTP::respond 301 Location "http://www.newdomain.com/en-US/destination1$newUri" } "/dir1" - "/dir1/" { HTTP::respond 301 Location "http://www.newdomain.com/fr-FR/destination2$newUri" } "/dir1/dir2" - "/dir1/dir2/" { HTTP::respond 301 Location "http://www.newdomain.com/fr-FR/destination3$newUri" } "/dir1/dir2/dir3" - "/dir1/dir2/dir3/" { HTTP::respond 301 Location "http://www.newdomain.com/fr-FR/destination4$newUri" } ... } The list goes on but the logic remains the same.
- Hannes_Rapp
Nimbostratus
Use -glob flag if you have wildcards or other expressions. With your current iRule, the -glob flag is not mandatory.
You may also want to have a look at LTM Local Traffic policy feature. I'd use a Local Traffic Policy over iRules these days whenever possible.
When it comes to shortening the iRule, Yann got the same solution posted a bit before me (removed mine)
- Arie
Altostratus
As far as I know Local Traffic Policies still don't allow control over the redirect type (301, 302, etc.). That being the case a policy may not be the best solution since often a 301 would be preferable.
It's disappointing that F5 is still not conforming to the RFCs on this. Hoping to see that soon!
- ShinRyuX
Nimbostratus
My comment on top didnt come out right. Here is the full Logic of my iRule.
when HTTP_REQUEST { Extract URL parameters set urlPath "[string tolower [HTTP::path]]?" if {[string tolower [HTTP::uri]] contains "?"} { set newUri [string map -nocase [list $urlPath "?"] [HTTP::uri]] } else { set newUri "" } Redirection Logic case switch -glob [string tolower [HTTP::path]] { "/file1.html" { HTTP::respond 301 Location "http://www.newdomain.com/en-US/destination1$newUri" } "/dir1" - "/dir1/" { HTTP::respond 301 Location "http://www.newdomain.com/fr-FR/destination2$newUri" } "/dir1/dir2" - "/dir1/dir2/" { HTTP::respond 301 Location "http://www.newdomain.com/fr-FR/destination3$newUri" } "/dir1/dir2/dir3" - "/dir1/dir2/dir3/" { HTTP::respond 301 Location "http://www.newdomain.com/fr-FR/destination4$newUri" } ... }The list goes on but the logic remains the same.
- Maybe you can define a data-group of type string. The string is dirX and the value is destinationX. Then you apply a trimleft on the HTTP::path to get the last part of the uri, then check the presence of that uri part within the data-group using a command similar to if { [class match $trimuri equals "uripart_dg" ] } { HTTP::respond 301 Location "http://www.newdomain.com/fr-FR/[class lookup $trimuri uripart_dg]$newUri" } and finally apply th
Maybe you can define a data-group of type string. The string is dirX and the value is destinationX. Then you apply a trimleft on the HTTP::path to get the last part of the uri, then check the presence of that uri part within the data-group using a command similar to :
if { [class match $trimuri equals "uripart_dg" ] } { HTTP::respond 301 Location "http://www.newdomain.com/fr-FR/[class lookup $trimuri uripart_dg]$newUri" }- VernonWells
Employee
I believe that the data group answer is the best one if you are in fact not performing globbing. Here is how I would do it (though not tested!):
tmsh create ltm data-group internal redirector-base type string { records add { \ "/file1.html" { data "http://www.newdomain.com/en-US/destination1" } \ "/dir1" { data "http://www.newdomain.com/en-US/destination2" } \ "/dir1/" { data "http://www.newdomain.com/en-US/destination2" } \ ... etc ... } }(You could -- and probably should -- do this with an imported external data-group, but I use an internal group for illustration).
Then the rule:
when HTTP_REQUEST { set base [class lookup "[HTTP::path]" redirector-base] if { $base ne "" } { Extract URL parameters set urlPath "[string tolower [HTTP::path]]?" if {[string tolower [HTTP::uri]] contains "?"} { set newUri [string map -nocase [list $urlPath "?"] [HTTP::uri]] } else { set newUri "" } HTTP::respond 301 Location "$base$newURI" } }Note a few things:
- This will not work if you need to employ globbing (though, strictly speaking, you could iterate through a list of glob matchers that are keys in a data-group, but that may be [considerably] less efficient than the switch);
- I moved the
computation inside of the conditional. If there is no match, there's no point in performing the calculation;$newURI - You use a pattern that I very commonly see, namely:
. While it is true that some filesystems are case-insensitive, RFC 2616 states that everything but the scheme (i.e., the leading 'http' in this case) and the hostname should be treated in a case-sensitive manner. See RFC 2616 3.2.3 [1]. As a practical matter, "flattening" the case of the path costs CPU cycles and I believe it to be of no practical value, especially if users are not typically typing in the uri-path part, but rather they are getting to these locations via hyperlinks.[string tolower [HTTP::path]]
[1] Specifically:
When comparing two URIs to decide if they match or not, a client SHOULD use a case-sensitive octet-by-octet comparison of the entire URIs, with these exceptions: - A port that is empty or not given is equivalent to the default port for that URI-reference; - Comparisons of host names MUST be case-insensitive; - Comparisons of scheme names MUST be case-insensitive; - An empty abs_path is equivalent to an abs_path of "/".
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
* 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