Forum Discussion

mraful_64014's avatar
mraful_64014
Icon for Nimbostratus rankNimbostratus
Mar 06, 2013

mimic sideband

I am trying to do something similar in 10.x that Sideband of 11.x allows. Is there anyway I can grab a web page in my iRule when the client connects or upon init for processing? I know all of the I/O commands have been stripped out of iRules, so that's out. Changing the URI when a client comes in merely directs them to the page I want to grab to look for the address that is in the X-Forwarded-For.

 

Thanks,

 

 

Mitch

 

5 Replies

  • Absolutely, though it's not nearly as intuitive. Before sideband calls, in order to do what you're asking you would use the HTTP::request and HTTP::retry commands. Essentially, in an HTTP request event (ingress flow), you capture the value of the client's request to a temporary variable using the HTTP::request command, then change the direction of flow using either the node or pool command (and optionally resetting the HTTP::uri value) to point to the new resource. When that server responds, you'll capture it in the HTTP_RESPONSE event, collect the payload (and do something with it), then reset the pool and request (from the saved client request) and issue an HTTP::retry. This then causes the flow to progress to the assigned application pool.

    Here's what it would generally look like:

    
    when CLIENT_ACCEPTED {
         set initial lookup status - do lookup
        set lookup 1
    }
    when HTTP_REQUEST {
        if { [info exists lookup] and $lookup == 1 } {
    
             Unset the lookup flag
            unset lookup
    
             Save the client's original request
            set request [HTTP::request]
    
             Save the original pool
            set default_pool [LB::server pool]
    
             Set to a new “sideband” IP and port
            node 10.70.0.1 80
    
             Set new URI for sideband request
             at this point ingress flow is diverted to the new resource (with a new URI).
            HTTP::uri "/http-retry-test.php"
        }
    }
    when HTTP_RESPONSE {
         The sideband response will return just like a regular response, 
         so you need a way of determining which is which. If you can 
         craft the web server's response so that it returns a unique 
         non-standard value, you can capture that here. Otherwise 
         you can set a temporary variable at the end of the 
         HTTP_REQUEST event and perform an "if { [info exists variable] }" 
         conditional in the HTTP_RESPONSE (make sure to unset the 
         variable right away).
        if { [HTTP::status] eq "600" } {
             collect the payload from the sideband response
            HTTP::collect [HTTP::header value Content-Length]
        }
    }
    when HTTP_RESPONSE_DATA {
         Capture payload data - this will be the sideband response data
        set payload [HTTP::payload]
    
         Reset to the original pool
        pool $default_pool
    
         Example: modify original (potentially modified) request with data from sideband call
        set new_request [string map "\"GET / \" \"GET /?sideband=[URI::encode $payload] \"" $request]
    
         Reset the original (potentially modified) request to the default pool
        HTTP::retry $new_request
    }
    

    The primary difference between this method and v11 sideband calls, aside from more intuitive coding, is that v11 sideband calls are blocking. When you issue a sideband call, the response is returned to the sideband object before anything else happens. With HTTP::request and HTTP::retry you have to capture the sideband response in a normal HTTP response event, so you have to be crafty about how you distinguish between regular and sideband responses. You can kind of think of the old method like a pendulum. You have to keep the momentum of the "ball" as it travels between the client and server, but the sideband call allows you to quickly tilt the table so that the ball will take a different path.

  • Hey Kevin, can I just confirm, is no $ required with the variable name when used with the info command in this line?

    
    if { [info exists lookup] and $lookup == 1 } {
    
  • That is correct. You don't use the $ sign in front of the variable inside the [info exists ] command.

     

     

    [info exists ] is a "set" command, like set and append, which all write to a variable. So what you're really saying is, "is this variable set?" (which has nothing to do with what may already be inside the variable).