Forum Discussion

Chadri_103513's avatar
Chadri_103513
Icon for Nimbostratus rankNimbostratus
Sep 01, 2009

ot Payload data npassing with POST inspection

Hi,

 

 

I need some help with an iRule that is designed to inspect both GET and POST data, compare it against a data-group of accepted commands, and then redirect it to the appropriate pool. The GET portion of this iRule is working, however, I am having issues with the POST portion. While debugging the iRule, I see that the POST portion is inspecting the traffic, matching the data-group, and rewriting the header but the payload doesn't appear to be making it back to the server. How do I make sure that all payload data is making it back to the server?

 

 

 

when HTTP_REQUEST {

 

set exampleHost "example.staging.local"

 

set examplePath "/exampleproxy/exampleproxy.aspx"

 

set examplePool "example.staging-80"

 

 

HTTP::header insert "OLD_HOST" [HTTP::host]

 

if { [HTTP::version] eq "1.1" } {

 

if { [HTTP::header is_keepalive] } {

 

HTTP::header replace "Connection" "Keep-Alive"

 

}

 

HTTP::version "1.0"

 

}

 

if { [HTTP::host] eq $exampleHost } {

 

pool $examplePool

 

return

 

}

 

elseif { [string tolower [HTTP::path]] eq "$examplePath"} {

 

HTTP::header replace "Host" $exampleHost

 

pool $examplePool

 

return

 

}

 

if { [HTTP::method] eq "GET"} {

 

set cmd [ URI::query [string tolower [HTTP::uri]] command ];

 

if { [matchclass $::example_staging equals $cmd] } {

 

HTTP::header replace "Host" $exampleHost

 

HTTP::path $examplePath

 

pool $examplePool

 

return

 

}

 

}

 

elseif { [HTTP::method] eq "POST" } {

 

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

 

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

 

} else {

 

HTTP::collect 256

 

}

 

 

}

 

}

 

when HTTP_REQUEST_DATA {

 

set cmd [string tolower [getfield [lsearch -inline [split [HTTP::payload] "&"] command=*] = 2]]

 

if {[matchclass $::example_staging equals $cmd]} {

 

HTTP::header replace "Host" $exampleHost

 

HTTP::path $examplePath

 

set payload [HTTP::payload]

 

pool $examplePool

 

return

 

}

 

}

 

 

 

Any help would be greatly appreciated.

 

 

Thanks.

3 Replies

  • maybe HTTP::release can help

     

    (put it before return inside HTTP_REQUEST_DATA. actually, you don't need return command there)

     

     

    Nat
  • hoolio's avatar
    hoolio
    Icon for Cirrostratus rankCirrostratus
    Hi,

    I'd be suspicious about the default of collecting 256 bytes for POST requests without a Content-Length header. Can you add logging to that portion of the rule:

     
     ... 
     elseif { [HTTP::method] eq "POST" } { 
      
        log local0. "[IP::client_addr]:[TCP::client_port]: POST request to [HTTP::host][HTTP::uri]\ 
           with Content-Length: [HTTP::header Content-Length]" 
        if { [HTTP::header exists "Content-Length"] } { 
           HTTP::collect [HTTP::header Content-Length] 
           log local0. "[IP::client_addr]:[TCP::client_port]: Collecting [HTTP::header Content-Length] bytes" 
        } else { 
           HTTP::collect 256 
           log local0. "[IP::client_addr]:[TCP::client_port]: No Content-Length, collecting 256 bytes: Req: [HTTP::request]" 
        }  
     } 
     when HTTP_REQUEST_DATA { 
      
        log local0. "[IP::client_addr]:[TCP::client_port]: Collected [HTTP::payload length] bytes: [HTTP::payload]" 
      
         Parse the command from the request payload 
         set cmd [string tolower [getfield [lsearch -inline [split [HTTP::payload] "&"] command=*] = 2]] 
        set cmd [string tolower [URI::query "?[HTTP::payload]" command]] 
      
        if {[matchclass $::example_staging equals $cmd]} { 
           log local0. "[IP::client_addr]:[TCP::client_port]: Matched $cmd, replacing host header, path and setting pool." 
           HTTP::header replace "Host" $exampleHost 
           HTTP::path $examplePath 
           pool $examplePool 
        } 
     }  
     

    Assuming you're parsing parameter names and values that are URL encoded in the format param1=value1&param2=value2, you could replace this line:

    set cmd [string tolower [getfield [lsearch -inline [split [HTTP::payload] "&"] command=*] = 2]]

    with this line:

    set cmd [string tolower [URI::query "?[HTTP::payload]" command]]

    I would guess the inbuilt processing of the parameters would be faster than the list commands.

    Aaron
  • hoolio's avatar
    hoolio
    Icon for Cirrostratus rankCirrostratus
    Hi Nat,

     

     

    The wiki page for HTTP::release says:

     

     

    http://devcentral.f5.com/wiki/default.aspx/iRules/http__release

     

     

    Releases the data collected via HTTP::collect. Unless a subsequent HTTP::collect command was issued, there is no need to use the HTTP::release command inside of the HTTP_REQUEST_DATA and HTTP_RESPONSE_DATA events, since (in these cases) the data is implicitly released.

     

     

    Do you think it still might be required? I was thinking the issue might be an atypical client sending a chunked request. In that case, the request wouldn't have a Content-Length header and could be hitting the HTTP::collect 256 statement.

     

     

    This seems like an odd problem, as the payload isn't being modified in any way...

     

     

    Thanks,

     

    Aaron