Forum Discussion

Pirlo's avatar
Pirlo
Icon for Nimbostratus rankNimbostratus
Dec 30, 2014

URI inspect - Rewrite - Redirect

DevGods

 

I am trying to inspect URI and Insert into a newly formatted redirect. I am trying to use the URI Interrogation code to dump the params then formulate the redirect.

 

If I read the code correctly I should be able to dump the query into param format then I FEASIBLY should be able to write a rule that would look something like this correct?

 

when HTTP_REQUEST {

 

set namevals [split [HTTP::query] "&"]

 

for {set i 0} {$i < [llength $namevals]} {incr i} {

 

set params [split [lindex $namevals $i] "="]

 

set pnum [expr $i+1]

 

log local0. "Param[$pnum]: [lindex $params 0]"

 

log local0. "Value[$pnum]: [URI::query [HTTP::uri] [lindex $params 0]]"

 

if { [HTTP::uri] starts_with "/receiptLocator" } {

 

HTTP::redirect "https://my.domain.com/ReceiptLocator=$pnum1&CityOrigin=$pnum2&FirstName=$pnum3&LastName=$pnum4"

 

URI Interrogation

 

Incoming URI I will inspect

 

receiptLocator=ABCDEF&originCity=BOS&firstName=John&lastName=Doe&language=en

 

Rewritten and Redirected URI

 

ReceiptLocator=ABCDEF&CityOrigin=BOS&FirstName=John&LastName=Doe

 

4 Replies

  • Your sample code loops through all query parameters and would send a redirect per parameter (as there is no closing curly bracket before doing the redirect).

     

    To make the code more rubust I would not count on the expected order of parameters. A jump table (switch) may help to assign the proper value to each parameter.

     

  • You can try the following code, please:

     

    when HTTP_REQUEST {
    
        if {[HTTP::query] ne "" && !([HTTP::query] starts_with "ReceiptLocator") } {
            set namevals [split [HTTP::query] "&"]
            log local0. "[HTTP::query]; number of params: <[llength ${namevals}]>"
    
            for {set i 0} {$i < [llength ${namevals}]} {incr i} {
                set param [split [lindex ${namevals} $i] "="]
                log local0. "current parameter: <$param>, <${i}> of <[llength ${namevals}]>"
                log local0. "param_name: <[lindex $param 0]>, param_value <[lindex $param 1]>"
                switch [string tolower [lindex $param 0]] {
                    "receiptlocator" { set ReceiptLocator [lindex $param 1] }
                    "origincity" { set CityOrigin [lindex $param 1] }
                    "firstname" { set FirstName [lindex $param 1]}
                    "lastname" {set LastName [lindex $param 1]}
                }
            }
            if { [info exists ReceiptLocator] && [info exists CityOrigin] && [info exists FirstName] && [info exists LastName] } {
                HTTP::redirect "HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::path]?ReceiptLocator=${ReceiptLocator}&CityOrigin=${CityOrigin}&FirstName=${FirstName}&LastName={LastName}"
            } else {
                log local0. "missing parameters"
            }
        } else {
            log local0. "no query data or query already in expected format"
        }
    }
  • this is just another example.

     configuration
    
    [root@ve11a:Active:In Sync] config  tmsh list ltm virtual bar
    ltm virtual bar {
        destination 172.28.24.10:80
        ip-protocol tcp
        mask 255.255.255.255
        pool foo
        profiles {
            http { }
            tcp { }
        }
        rules {
            qux
        }
        source 0.0.0.0/0
        source-address-translation {
            type automap
        }
        vs-index 2
    }
    [root@ve11a:Active:In Sync] config  tmsh list ltm rule qux
    ltm rule qux {
        when RULE_INIT {
      set static::param {receiptLocator originCity firstName lastName}
      set static::newparam {ReceiptLocator CityOrigin FirstName LastName}
      set static::len [llength $static::param]
    }
    when HTTP_REQUEST {
      if { [HTTP::uri] starts_with "/receiptLocator" } {
        set newuri "/"
        for {set i 0} {$i < $static::len} {incr i} {
          set pvalue [URI::query "?[string trimleft [HTTP::uri] /]" [lindex $static::param $i]]
          if { $newuri ne "/" } {
            append newuri "&"
          }
          append newuri "[lindex $static::newparam $i]=$pvalue"
        }
        HTTP::redirect "http://[HTTP::host]$newuri"
      } else {
         do nothing
      }
    }
    }
    
     test
    
    [root@ve11a:Active:In Sync] config  curl -i "http://172.28.24.10/receiptLocator=ABCDEF&originCity=BOS&firstName=John&lastName=Doe&language=en"
    HTTP/1.0 302 Found
    Location: http://172.28.24.10/ReceiptLocator=ABCDEF&CityOrigin=BOS&FirstName=John&LastName=Doe
    Server: BigIP
    Connection: Keep-Alive
    Content-Length: 0
    
    
  • I noticed a mistake in my first sample (missing variable declaration in response definition).

     

    (For whatever reason I cannot change the previous post.)

     

    Here is the corrected code including a switch for turning debugging on/off and allowing both ampersand and semicolon for parameter separation in query:

     

    when HTTP_REQUEST {
    
         enable (1), disable (0) debugging
        set debug 0
        if {[HTTP::query] ne "" && !([HTTP::query] starts_with "ReceiptLocator") } {
    
             split query into parameters separated by semicolon or ampersand
            set namevals [split [HTTP::query] ";&"]
            if { $debug > 0 } {
                log local0. "original query: <[HTTP::query]>; number of params: <[llength ${namevals}]>"
            }
    
             loop through all parameters
            for {set i 0} {$i < [llength ${namevals}]} {incr i} {
    
                 read parameter name and value
                set param [split [lindex ${namevals} $i] "="]
                if { $debug > 0 } {
                    log local0. "current parameter: <$param>, <[expr {${i} + 1}]> of <[llength ${namevals}]>"
                    log local0. "param_name: <[lindex $param 0]>, param_value <[lindex $param 1]>"
                }
    
                 assign variable values for redirect
                switch [string tolower [lindex $param 0]] {
                    "receiptlocator" { set ReceiptLocator [lindex $param 1] }
                    "origincity" { set CityOrigin [lindex $param 1] }
                    "firstname" { set FirstName [lindex $param 1]}
                    "lastname" {set LastName [lindex $param 1]}
                }
            }
    
             redirect only if variables are set
            if { [info exists ReceiptLocator] && [info exists CityOrigin] && [info exists FirstName] && [info exists LastName] } {
                HTTP::redirect "HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::path]?ReceiptLocator=${ReceiptLocator}&CityOrigin=${CityOrigin}&FirstName=${FirstName}&LastName=${LastName}"
            } else {
                if { $debug > 0 } {
                    log local0. "missing parameters in query"
                }
            }
        } else {
            if { $debug > 0 } {
                log local0. "no query data or query already in expected format"
            }
        }
    }
    

    For testing locally on the F5 device I´m using the same approach as Nitass:

     

     curl -i http://10.131.131.120/test?receiptLocator=ABCDEF\;originCity=BOS\;firstName=John\&lastName=Doe\;language=en
    HTTP/1.0 302 Found
    Location: HTTP::redirect https://10.131.131.120/test?ReceiptLocator=ABCDEF&CityOrigin=BOS&FirstName=John&LastName=Doe
    Server: BigIP
    Connection: Keep-Alive
    Content-Length: 0