Forum Discussion

KenG's avatar
KenG
Icon for Nimbostratus rankNimbostratus
Jul 10, 2014

Variable Scope with HTTP requests and collected data

I would like to be able to direct a request based on the content of some of the XML content in the request body. So far I have only ever done this in the HTTP_REQUEST event. In fact we have a basic framework that means all I need to do is set a variable "poolname" in the HTTP_REQUEST event and another irule will do all the error handling of non-existant pools or unavailable nodes etc and will deal with the request from there.

 

In this case I need to collect payload with HTTP::collect and I set a variable in the HTTP_REQUEST_DATA event. It appears this variable is not available after the HTTP:collect line in the HTTP_REQUEST event.

 

Is that expected?

 

e.g In the code below action will always be logged as unknown. If I put the log line in an HTTP_RESPONSE block it has been set correctly, so the code is working.

 

when HTTP_REQUEST {
    set vhost [HTTP::host]:[TCP::local_port]
    set action "unknown"
    if {[HTTP::header "Content-Length"] ne "" && [HTTP::header "Content-Length"] <= 1048576}{
            set req_length [HTTP::header "Content-Length"]
          } else {
                set req_length 1048576
          }
    if { $req_length > 0} {
      HTTP::collect $req_length
    }
    log local0.info "Reqest $vhost with $action action\r\n"
}
WHEN HTTP_REQUEST_DATA {
  if { $req_contenttype starts_with "text/xml" } {
    set soapstart [ expr { [string first "" [HTTP::payload]] + 13 } ]
    set soapend [expr {$soapstart + 20}]
    set action [string range [HTTP::payload] $soapstart $soapend]
 }
  HTTP::release   
 }

4 Replies

  • Control passes directly to the HTTP_REQUEST_DATA event when you issue an HTTP::collect, and more important, the action variable that you're trying to see doesn't get set until after some processing in the HTTP_REQUEST_DATA event. If you put that log line anywhere in the HTTP_REQUEST_DATA event, after the set action line, you should see the variable with the correct value.

     

  • No, control does not pass back to HTTP_REQUEST after HTTP_REQUEST_DATA is triggered, but that's okay. All of the values and context of the first event are relevant in the second.

     

  • That seems quite anoying but I must just be over/under thinking it.

     

    One of the toughest things I had to grasp, as a traditional programmer learning iRules, is that iRules don't follow the same "flow" paradigm that other modern languages follow. True to form, an iRule "script" flows procedurally from top to bottom like any other program, but it does so in the context of network flow. Events are triggered in the context of the OSI layer that they represent. CLIENT ACCEPTED (layer 4) happens first, then CLIENTSSL_HANDSHAKE (layer 6 - and if offloading SSL), then HTTP_REQUEST, HTTP_REQUEST_DATA if triggered by an HTTP::collect, the LB:: events in the middle, HTTP_REQUEST_SEND and _RELEASE, and then proceeding into the server side context with SERVER_CONNECTED (layer 4), and finally HTTP_RESPONSE (layer 7). If you think of it in this "left to right" sort of way, then it starts to make sense how IP information is available to an HTTP_REQUEST event, but HTTP URI is not available in CLIENT_ACCEPTED.

     

  • When multiple iRules are applied to a single VIP, and those iRules have the same events, the compiler actually merges the events together. Two HTTP_REQUEST events become one HTTP_REQUEST event with merged code. Priority and ordering obviously become very important in this case.