Forum Discussion

andreoli_4699's avatar
andreoli_4699
Icon for Nimbostratus rankNimbostratus
Jan 13, 2010

HTTP::payload replace with MORE data?

Hi all, I have the following code:

 

 

      
      when HTTP_REQUEST priority 300 {      
      set original_payload [HTTP::payload]      
      set original_length [HTTP::header value Content-Length]      
      if { [lindex $session_var 7] == 1  and not ( [info exists all_done] ) } {      
      set original_request [HTTP::request]      
      HTTP::uri "/lookup.asp?id=[lindex $session_var 6]"      
      snatpool legacy-connect_snat      
      pool lookup.pool      
      event HTTP_REQUEST disable      
      } elseif { [info exists all_done] and $all_done == 1 } {      
      lset session_var 7 2      
      HTTP::header replace SOFTCERT_NUM $authkey      
      unset all_done      
      }      
      }      
            
      when HTTP_RESPONSE priority 300 {      
      if { [lindex $session_var 7] == 1  and not ( [info exists all_done] ) } {      
      HTTP::collect 1      
      }      
      }      
            
      when HTTP_RESPONSE_DATA priority 300 {      
      if { [lindex $session_var 7] == 1 and not ( [info exists all_done] ) } {      
      set authkey [HTTP::payload]      
      set all_done 1      
      event HTTP_REQUEST enable      
      HTTP::header replace "Content-Length" $original_length      
      HTTP::payload replace 0 $original_length $original_payload      
      HTTP::retry $original_request      
      }      
      }      
      

 

 

(Note that a few things, like session_var, are set by another script)

 

 

The purpose of this is to intercept a request, store the payload and length (1665 bytes) to a local variable, then take certificate information, and, by replacing the URI and doing a "pool" statement, go off and look up some data on another server. Upon return, it takes the reply data (10 bytes), stuffs it into another header, then HTTP::payload replace with what was originally gathered at the beginning. It then does a HTTP::retry with the original request.

 

 

Everything seems to be working great until I go to replace the payload, then it bombs with a "list index out of range". By playing around, it seems that since my payload went from 1665 bytes down to 10 through the lookup, it won't let me replace the payload with anything more than 10 bytes.

 

 

Does anyone have any idea how I can increase the buffer size that's allocated to this new payload so that I can replace it with the original data for my http::retry?

 

 

This is my first post, and I've been looking at this until my eyes bled, so be gentle 😉

 

 

Thanks!

 

Tony

15 Replies

  • I agree, and am going to place a call with them today, but it's really wierd. I've removed all of my code now, the only custom code running is this:

     

     

    when HTTP_REQUEST {

     

    log local0. "Payload Length:[HTTP::payload length]:"

     

    log local0. "Content Length:[HTTP::header value Content-Length]:"

     

    log local0. "Payload:[HTTP::payload]:"

     

    }

     

     

    On larger payloads, the Payload Length returns zero, while the Content Length shows the right value. In those instances, Payload is blank, and I can see in a tcpdump that the soap envelope begins in the second packet. On smaller payloads, the lengths and payload are correct, and I can see the payload actually begin in the first packet.

     

     

    Could it be something I'm doing wrong? Is the payload not available to the http_request event? That can't be, the smaller one works fine and besides, I have no control over whether the envelope begins in the first or second packet.

     

     

    Very wierd!
  • I should note that I've tried this both on my 9.4.4 65.1 and 9.4.8 355.0 boxes.
  • spark_86682's avatar
    spark_86682
    Historic F5 Account
    The HTTP_REQUEST event will fire when all of the HTTP headers have been received. This is because most iRules are only concerned about the headers and most HTTP requests only have headers, so it would not make sense to buffer the entire payload before firing it.

     

     

    Therefore, you can't count on any payload being accessible in the HTTP_REQUEST event. If any payload happens to have been received when the HTTP_REQUEST event fires, you will be able to access it in that event. This explains the behavior you're seeing with regards to packet boundaries. If you want to reliably examine or modify the payload, you should use HTTP::collect and the HTTP_REQUEST_DATA event.
  • And that was another possibility I was wondering about, me not looking in the right event.

     

     

    What I'm trying to do with this irule is to halt the initial request so that I can take some header data and do a lookup against another server. As the soap envelope is in there, I have to grab the payload and store it, otherwise it'll be lost when I do the lookup. Once the lookup succeeds, I want to put the initial uri and payload back in, and let it go on it's way.

     

     

    I still don't fully understand the order of events, is there somewhere you can point me to that would help clarify when each event fires?

     

  • http://devcentral.f5.com/weblogs/jason/archive/2009/09/08/irules-insight-http-event-order.aspx Click here