Forum Discussion

Yozzer's avatar
Yozzer
Icon for Nimbostratus rankNimbostratus
Dec 13, 2010

Search payload and redirect to payload value

Hi

 

 

I need some help with the irule below. I want to search for a POST data name 'Relay" and then check its value and then redirect the POST to the Relay value . Relay could have a few different values to redirect to. Any help would be great. Thanks

 

 

when RULE_INIT {

 

 

Default amount of request payload to collect (in bytes)

 

set static::collect_length 2048

 

 

}

 

 

when HTTP_REQUEST {

 

 

Only check POST requests

 

if {([HTTP::method] == "POST") && ([HTTP::uri] == "/test")} {

 

 

Check for a non-existent Content-Length header

 

if {[HTTP::header Content-Length] eq ""}{

 

 

Use default collect length of 1k for POSTs without a Content-Length header

 

set collect_length $static::collect_length

 

 

} elseif {[HTTP::header Content-Length] == 0}{

 

 

Don't try collect a payload if there isn't one

 

unset collect_length

 

 

} elseif {[HTTP::header Content-Length] > $static::collect_length}{

 

 

Use default collect length

 

set collect_length $static::collect_length

 

 

} else {

 

 

Collect the actual payload length

 

set collect_length [HTTP::header Content-Length]

 

 

}

 

 

If the POST Content-Length isn't 0, collect (a portion of) the payload

 

if {[info exists collect_length]}{

 

 

Trigger collection of the request payload

 

HTTP::collect $collect_length

 

}

 

}

 

}

 

 

when HTTP_REQUEST_DATA {

 

foreach p [split [HTTP::payload] &] {

 

set name [URI::decode [getfield $p = 1]]

 

set value [URI::decode [getfield $p = 2]]

 

if {[$name = "Relay" and $value contains "/test2/"]} {

 

HTTP::redirect "https://test.com/test2/login.aspx"

 

}

 

}

 

}

9 Replies

  • Maybe something like this?

    when RULE_INIT {
    
        Default amount of request payload to collect (in bytes)
       set static::collect_length 2048
    }
    
    when HTTP_REQUEST {
    
        Only check POST requests
       if {([HTTP::method] eq "POST") && ([HTTP::uri] eq "/test")} {
    
           Check for a non-existent Content-Length header
          if {[HTTP::header Content-Length] eq ""}{
    
              Use default collect length of 1k for POSTs without a Content-Length header
             set collect_length $static::collect_length
    
          } elseif {[HTTP::header Content-Length] == 0}{
    
              Don't try collect a payload if there isn't one
             unset collect_length
    
          } elseif {[HTTP::header Content-Length] > $static::collect_length}{
    
              Use default collect length
             set collect_length $static::collect_length
    
          } else {
    
              Collect the actual payload length
             set collect_length [HTTP::header Content-Length]
    
          }
    
           If the POST Content-Length isn't 0, collect (a portion of) the payload
          if {[info exists collect_length]}{
    
              Trigger collection of the request payload
             HTTP::collect $collect_length
          }
       }
    }
    
    when HTTP_REQUEST_DATA {
       set relay [URI::decode [URI::query "?[HTTP::payload]" Relay]]
       if {$relay ne ""}{
          HTTP::redirect "https://test.com$relay"
       }
    }
    

    Aaron
  • Yozzer's avatar
    Yozzer
    Icon for Nimbostratus rankNimbostratus
    Thanks Aaron,

     

     

    Relay may already contain https://test.com/test2/login.aspx so i would redirect if it contained a value:

     

     

    when HTTP_REQUEST_DATA {

     

    set relay [URI::decode [URI::query "?[HTTP::payload]" Relay]]

     

    if {$relay contains "/test2/"}{

     

    HTTP::redirect "https://test.com/test2/login.aspx"

     

    if {$relay contains "/test3/"}{

     

    HTTP::redirect "https://test.com/test3/login.aspx"

     

    }

     

    }

     

    }

     

     

     

    Would this work?

     

     

    Thanks

     

     

  • That would probably work, but this is a bit more efficient:

    
    when HTTP_REQUEST_DATA {
       switch -glob [URI::decode [URI::query "?[HTTP::payload]" Relay]] {
          "*/test2/*" {
             HTTP::redirect "https://test.com/test2/login.aspx"
          }
          "*/test3/*" {
             HTTP::redirect "https://test.com/test3/login.aspx"
          }
       }
    }
    

    Aaron
  • Yozzer's avatar
    Yozzer
    Icon for Nimbostratus rankNimbostratus
    Hi Aaron

     

     

    I tried both rules and noticed that the redirect performed a GET request but didnt include the POST data. What would i have to add to perform a redirect of all the POST data to the Relay value?

     

     

    Thanks for your help.
  • Yozzer's avatar
    Yozzer
    Icon for Nimbostratus rankNimbostratus

     

    I found this from a previous post and added your recommendations but found it doesnt save the rule on the BIGIP or give me feedback on its syntax. Also when posting the last part renders html which i took from the "Redirect POST data while load balancing GET iRule" http://devcentral-sea.f5.com/Forums/tabid/1082223/asg/50/showtab/groupforums/aff/5/aft/1172096/afv/topic/Default.aspx :

     

     

    when HTTP_REQUEST {

     

     

    if {([HTTP::method] eq "POST") && ([HTTP::uri] eq "/test")} {

     

    HTTP::collect [HTTP::header "Content-Length"]

     

    }

     

    }

     

     

     

    when HTTP_REQUEST_DATA {

     

    switch -glob [URI::decode [URI::query "?[HTTP::payload]" Relay]] {

     

    "*/test2/*" {

     

    set static::ext_url "https://test.com/test2/login.aspx"

     

    }

     

    "*/test3/*" {

     

    set static::ext_url "https://test.com/test3/login.aspx"

     

    }

     

     

    set content " \

     

    <form>>> name=f action='$static::ext_url' method=post>"

     

     

    foreach p [split [HTTP::payload] &] {

     

    set name [getfield $p = 1] set value [decode_uri [getfield $p = 2]]

     

    set content "${content}" }

     

    set content "${content}</form>"

     

     

    HTTP::respond 200 content $content

     

     

    }
  • Yozzer's avatar
    Yozzer
    Icon for Nimbostratus rankNimbostratus
    Hi

     

     

    I managed to resolve this apart from this line:

     

     

    set content "'document.forms.submit();'"

     

     

     

    I want to add in [0] like this in a string:

     

     

     

    set content "'document.forms[0].submit();'"

     

     

     

    but its not allowing me.

     

     

    Any ideas?
  • Can you try the format from this Codeshare example?

     

     

    http://devcentral.f5.com/wiki/default.aspx/iRules/HTTP_POST_redirectNew118.html

     

     

    If that doesn't work, can you post the iRule in [ code ] [/ code ] blocks without the spaces to preserve the iRule spacing?

     

     

    Thanks, Aaron
  • A simpler option could be to append the payload to the redirect location. This assumes the client sends a URL encoded post data and the application accepts the parameters in the query string. It has the advantage of not looping through the parameters by name and not depending on Javascript.

    
    when HTTP_REQUEST_DATA {
       switch -glob [URI::decode [URI::query "?[HTTP::payload]" Relay]] {
          "*/test2/*" {
             HTTP::redirect "https://test.com/test2/login.aspx?[HTTP::payload]"
          }
          "*/test3/*" {
             HTTP::redirect "https://test.com/test3/login.aspx?[HTTP::payload]"
          }
       }
    }
    

    Aaron
  • Yozzer's avatar
    Yozzer
    Icon for Nimbostratus rankNimbostratus
    Thanks Aaron

     

     

    I added in a back slash and it worked.

     

     

    set content "'document.forms/[0/].submit();'"

     

     

    Thanks for your help on this.