Forum Discussion
Best Practice: Regex vs number of if/else
I previously had a rule that had:
if {
$login == 1 &&
([string first "OP=help" [HTTP::header "location"]] == -1) &&
([string first "OP=token_login" [HTTP::header "location"]] == -1) &&
([string first "OP=error" [HTTP::header "location"]] == -1) &&
([string first "ERR_CODE=0x13212077 " [HTTP::header "location"]] == -1) &&
([string first "ERR_CODE=0x132120c8" [HTTP::header "location"]] == -1) &&
([string first "OP=acct_locked" [HTTP::header "location"]] == -1) } {
} {
..do something...
}
I then thought that this was a bit inefficient as you would have to traverse each condition before "doing something". I thought i would change this to a regex:
if { $login == 1 &&
([regexp "OP=help|OP=token_login|OP=error|ERR_CODE=0x13212077|ERR_CODE=0x132120c8|OP=acct_locked" [HTTP::header "location"]] == 0)
} {
..do something...
}
But reading some solutions on AskF5 and the iRule 101 Blogs it seems that F5 generally recommend avoiding regex for simple cases.
So I thought i would ask the masses....any experience or any advice on what is the best approach?
Thanks in advance,
NJ
10 Replies
- Patrick_Chang_7Historic F5 AccountWe say to avoid REGEX because it can be greedy and inefficient. In this case, I would say that it should be fine if [HTTP::header "location"] is not too long a string (say 30 characters or less).
- Naman_65674
Nimbostratus
Actually the string can get quite long....up to 180 characters if not more.... - Patrick_Chang_7Historic F5 AccountIn that case, I would stick with the original.
- spark_86682Historic F5 AccountIf your logic really looks like that (wanting to detect the absence of any of a number of strings in the same place), then you might also look into creating a class (data group) with your strings and using the class command, which might be even more efficient.
- Naman_65674
Nimbostratus
That actually might be a good idea spark, as i would be able to add the list quite easily.
So if i had a dataclass with:
class error_msgs {
"OP=help"
"OP=token_login"
"OP=error"
"ERR_CODE=0x13212077"
"ERR_CODE=0x132120c8"
"OP=acct_locked"
}
Would it be as simple as:
if { [matchclass $::error_msgs contains [HTTP::header "location"]] == 0 } {
...do something...
}
I got a bit worried reading the matchclass wiki doco, especially:
"And this example will will return the index of the first row containing any of contiguous characters in the string "green" (g, r, e, n, gr, re, ee, en, gre, ree, een, gree, reen, and green will all match):
[matchclass "green" contains $::data_group]"
I only want it to compare on the whole word.....
-- NJ - Naman_65674
Nimbostratus
Can anyone advise on the way I have used matchclass above? - Michael_Yates
Nimbostratus
Hi Naman,
I am guessing that you are running v9.x.x if you are using "matchclass". If you are running v10.x.x you should use "class match".
Try this:if { [matchclass [HTTP::header "Location"] contains $::error_msgs ] } { ....do something... } - Naman_65674
Nimbostratus
(Yes i am using v9.4.8)Thanks for the tip. I noticed however that in the DevCentral wiki page on matchclass it said the following:
"Note that you should not use a $:: or :: prefix on the datagroup name when using the matchclass command (or in any datagroup reference) on 9.4.4 or later. For details, see theCMP compatibility page."So do we use instead of "$::"Thanks,Naman - nitass
Employee
just removing $::
e.g.if {[matchclass [HTTP::header "Location"] contains error_msgs] } { ....do something... } - Michael_Yates
Nimbostratus
Hi Naman,
To add a little bit more to what you posted about the variables. On the CMP compatibility page it says:
Global Variables
9.4.x global variables not compatible with CMP Note - demoted only if caught by validator--"global" keyword was not caught by validator (:: reference)
Not CMP compatible:
set val "$::www_redir https://${host}:${port}[HTTP::uri]\r\n$::www_opts"
CMP compatible (v9.x):
set val "[findclass "www_redir" global_vars " "] https://${host}:${port}[HTTP::uri]\r\n[findclass "www_opts" global_vars " "]"
So the "$::" and "::" variable designation will still "work", but it makes the iRule CMP Non-Compliant. The impact of that would tie all traffic to the default TMM0 when processing this iRule in a CMP environment.
Best practices are to remove it, but when you upgrade to 10.x.x, stop using the "classmatch" command all together and more to the "class match" command instead.
Hope this helps.
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
