Forum Discussion
irule class match each query param separately
Data Group dg1
param1=p11¶m2=p21 := host1
param1=p12¶m2=p22 := host2
The problem is that some request urls might list their query params in reverse order
param2=p21¶m1=p11
Therefore I need to match query params individually.
So I have two problems to solve :
-
extract from
the param segments for[HTTP::query]
andparam1
param2
-
determine if both
andparam1_segment
are found together in some key inparam2_segment
dg1
So something like :
set param1 "param1"
set param2 "param2"
set param1_segment = [[HTTP:query] $param1]
set param2_segment = [[HTTP:query] $param2]
if { (class match $param1_segment&$param2_segment equals dg1) or (class match $param2_segment&$param1_segment equals dg1) } {
NOTE: I know the above is wrong in terms of both language elements and syntax. I'm just providing to better describe the problem I need to solve.
Because my use-case might extend to 3 query params ( in any order ) it might be better to AND together class match for each query param segment.
- Kevin_StewartEmployee
I think it would almost make more sense to just reorder the params, and then look them up in the data group. So something like this:
when HTTP_REQUEST { if { [URI::query [HTTP::uri]] ne "" } { set param1 [URI::query "?[URI::query [HTTP::uri]]" param1] set param2 [URI::query "?[URI::query [HTTP::uri]]" param2] set param3 [URI::query "?[URI::query [HTTP::uri]]" param3] set paramstring "param1=$param1¶m2=$param2¶m3=$param3" if { [class match $paramstring equals dg1] } { ... do something here ... } } }
You'll of course need some additional error checking in there, to make sure params exist, but you get the idea.
- Aaron_Forster_3Historic F5 Account
Your use case might extend to three parameters as in if it extends it will always have three or as in a request may have two or may have three?
If you want to pull out individual parameters and re-order them you can extract with URI::query. Unlike HTTP::query it doesn't pull from the existing request, you have to feed it a URI to extract the query from. It has two forms. The first simply extracts the query portion like HTTP::query (but could be used on a source other than the current request) and the second extracts a specific parameter. you would call it like this:
[URI::query [HTTP::uri] param1]
which would return "param1" from the above request.
You could use this to quickly re-order the values of the parameters.
set param1 "param1" set param2 "param2" set param1_segment = [URI::query [HTTP::uri] $param1] set param2_segment = [URI::query [HTTP::uri] $param2]
Now the class command has a number of different ways you can call it. equals really only tells you that what you are looking for matches one of the entries in it. you can also add the -value flag to get the value of that option. I.E.
class match -value $param1_segment&$param2_segment equals dg1 wouldn't return true for "param1=p11¶m2=p21" it would return host1.
The upshot is you just construct a single lookup. put param1 and 2 together, if 3 exists add that one.
last bit is to avoid having to stuff all those various possible combinations together you simply stuff them together in the correct order. assign the results to what ever you're going to use it for (variable, pool selection, etc) and to avoid errors/have a fallback if it doesn't exist wrap the whole thing in a TCL catch statement
if { [catch {pool class match -value $param1_segment&$param2_segment equals dg1}] { pool fallBackPool }
The contents of the if statement will be executed only if the first pool assignment fails. which it would if there was no pool returned from the class match value.
EDIT: My first attempt to post a response failed so I had to retype it and forgot to add links URI::query https://devcentral.f5.com/wiki/iRules.URI__query.ashx
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