Forum Discussion

Cosby_17532's avatar
Cosby_17532
Icon for Nimbostratus rankNimbostratus
Feb 23, 2011

Using wildcards with classes

I'm in desperate need of help with an iRule for a customer. They are converting a working 9.x rule to 10.x. In the process we changed it from an array to a class. The class calls an external file with 8998 lines (I know it's rather large). What they are doing is redirecting on the HTTP Response. They read the name from the class and then redirect (301) with the value.

 

 

The redirection portion works perfectly. The problem is that the name portion has a lot of wildcard URIs and I can't figure out how to deal with them.

 

 

I'm posting a portion of a test data set, the current iRule, and the class commands from the config. I would really appreciate any help I can get.

 

 

testdatagroup_file

 

 

"/A1/" := "http://192.168.201.250/a.html",

 

"/A1/*" := "http://192.168.201.250/Athens/a.html",

 

"/B1/" := "http://192.168.201.250/b.html",

 

"/B1/*" := "http://192.168.201.250/Boston/b.html",

 

"/C1/" := "http://192.168.201.250/c.html",

 

"/C1/*" := "http://192.168.201.250/Chicago/c.html",

 

"/D1/" := "http://192.168.201.250/d.html",

 

"/D1/*" := "http://192.168.201.250/Dallas/d.html",

 

"/E1/" := "http://192.168.201.250/e.html",

 

"/E1/*" := "http://192.168.201.250/Elvira/e.html",

 

"/F1/" := "http://192.168.201.250/f.html",

 

"/F1/*" := "http://192.168.201.250/Franklin/f.html",

 

"/g/" := "http://192.168.201.250/g.html",

 

"/g/*" := "http://192.168.201.250/Gulf/g.html",

 

"/h/" := "http://192.168.201.250/h.html

 

"/h/*" := "http://192.168.201.250/Hanover/h.html

 

"/i/" := "http://192.168.201.250/i.html

 

"/i/*" := "http://192.168.201.250/indigo/i.html

 

 

class testdatagroup {

 

type string

 

filename "/config/testdatagroup_file"

 

separator ":="

 

}

 

redirectirule

 

 

 

Set debug to non-zero in the events you want to debug

 

debug levels: 0 - warnings only, 1 - testing, 2 - verbose

 

WARNING: verbose logging will be enormous with production dataset

 

 

when HTTP_REQUEST {

 

set debug 2

 

Set data variables

 

set HTTP_URI [HTTP::uri]

 

set HTTP_HOST [HTTP::host]

 

foreach element testdatagroup {

 

if {[string match -nocase $element $HTTP_URI]}{

 

log local0.notice "Element $element"

 

break

 

}

 

}

 

if { $debug > 0 } {log local0.notice "HTTP_URI set to [HTTP::uri] and HTTP_HOST set to [HTTP::host]."}

 

HTTP Redirect if correct

 

if { [string tolower ${HTTP_URI}] starts_with "/search?" and [URI::query ${HTTP_URI}] != ""} {

 

set my_query [URI::query ${HTTP_URI}]

 

if {$debug > 0} {log local0. "Redirecting ${HTTP_URI} to http://[HTTP::host]/Search/?${my_query}"}

 

HTTP::redirect "http://[HTTP::host]/Search/?${my_query}"

 

return

 

}

 

}

 

when HTTP_RESPONSE {

 

set dgname "testdatagroup"

 

if { $debug > 0 } {log local0.notice "Data Group: $dgname"}

 

log local0.notice "URIPATH [URI::path $HTTP_URI]"

 

set DG_name [class search -name testdatagroup contains $HTTP_URI ]

 

log local0.notice "DG_name: $DG_name"

 

if { [string match "\*" "${DG_name}"]} {

 

set name [class match -name $HTTP_URI starts_with testdatagroup ]

 

set value [class match -value $HTTP_URI contains testdatagroup]

 

if { $debug > 0 } {log local0.notice "Name Value: $name"}

 

} else {

 

set name [class match -name $HTTP_URI starts_with testdatagroup ]

 

set value [class match -value $HTTP_URI contains testdatagroup]

 

if { $debug > 0 } {log local0.notice "Name Value: $name"}

 

}

 

set newmap [class search -value testdatagroup equals [class match -name $HTTP_URI starts_with testdatagroup ]]

 

if { $debug > 0 } {log local0.notice "Redirect: $newmap"}

 

HTTP::respond 301 Location "$newmap"

 

}

 

 

Once again, I would appreciate any help at all.

 

 

Cosby

 

  • Hi Cosby,

     

     

    I'd break up the datagroup into one that has all of the "equals" matches (/A1/, /B1/, etc) and another that has the "starts_with" matches (/A1/*, /B1/*, etc entered in the datagroup as /A1/, /B1/, etc). You can then use [class match -element [HTTP::path] equals uris_datagroup] and [class match -element [HTTP::path] starts_with uris_datagroup].

     

     

    Aaron
  • Aaron,

     

     

    Thank you for your reply. I'm not sure I made myself clear. The data set has wildcards in it because the users may enter almost anything in. For example, the user may enter www.corpwebsite.com/petfriendsshop/en_US/doggiebites/123456/catalog.pdf. In the data set we may have the following entries:

     

     

    "/petfriendsshop/" := www.corpwebsite.com/petfriendsshop/intl/dogfood/123456/catalog.pdf

     

    "/petfriendsshop/en_US*" := www.corpwebsite.com/petfriendsshop/en_US/dogfood/123456/catalog.pdf

     

     

    The second entry is a wild card entry, no matter what is entered by the customer it should redirect them properly. As long as the URI starts with /petfriendsshop/en_US/.

     

     

    Cosby

     

  • Yep, so for any exact match like /petfriendshhop/, you'd add it to the exact match datagroup and use the equals operator. For a URI token that has a * on the end, you'd add it without the * to a "starts_with" datagroup and use the "starts_with" operator on class match. Similarly, if you had ends_with checks you wanted to do, you could use the same logic as starts_with. If you need to support wildcards in the middle of strings in the datagroup, you'd need to retrieve the entire datagroup as a TCL list using 'class get' and then loop through the entries one by one using 'string match'.

     

     

    Aaron
  • Hi Hoolio,

     

     

    Has there been any developments in the later versions of v10 or v11 that support exact and wildcard URLs in the same datagroup? We would like to use class match to do this but conscious of its limitations.
  • +1 this feature would be great! and also supporting wildcards when creating data-groups with tmsh

     

  • Arie's avatar
    Arie
    Icon for Altostratus rankAltostratus

    You can work around the limitation by moving the match indicator (wildcard vs. exact match) to the value and using a separator.

     

    In other words,

     

    "/g/*" := "http://192.168.201.250/Gulf/g.html"

     

    becomes

     

    "/g/" := "*;http://192.168.201.250/Gulf/g.html"

     

    and

     

    "/E1/" := "http://192.168.201.250/e.html"

     

    becomes

     

    "/E1/" := "=;http://192.168.201.250/e.html"

     

    This way you can build logic into your code to handle the two scenarios. I can elaborate if necessary.