Forum Discussion

commsmonkey_172's avatar
commsmonkey_172
Icon for Nimbostratus rankNimbostratus
Sep 30, 2011

Store variable from STREAM::expression and use in HTTP_RESPONSE context

Hi F5ers,

 

 

I've been looking for a way to store the stream matched hostname in a HREF from a HTML stream.

 

 

 

As I rewrite the content from internal domain to external domain using the stream filter I also need to store a portion of the rewritten value, as a cookie, and pass it on to the client so that when they return to the HREF'd location I can persist to the origin node (which is only identified through the HREF not through a direct or even proxied connection).

 

 

 

 

 

All and any advice appreciated!

 

 

 

Cheers,

 

 

 

Comms

 

  • Hi Comms,

     

     

    You can use STREAM::match to get the full matched string in the STREAM_MATCHED event:

     

     

    http://devcentral.f5.com/wiki/iRules.stream.ashx

     

     

    Aaron
  • Hi Aaron,

     

     

    I thought that was logical too and I've tried that without success prior to posting. It appears the variable set in the STREAM_MATCHED event is reported as out of scope or not known to the HTTP_RESPONSE event, similarly HTTP cookie creation and insertion is out of scope in the STREAM_MATCHED event.

     

     

    Here's the code with logging enabled for logic debugging:

     

     

    
     when STREAM_MATCHED  {
    set myVar [string tolower [getfield [STREAM::match] "." 1]]
    log local0.emerg  " myVar variable is $ myVar"
    }
    when HTTP_REQUEST {
        Disable the stream filter for all requests via VS
       STREAM::disable
    }
    when HTTP_RESPONSE {
        Disable the stream filter by default
    STREAM::disable
         Enable the stream filter for text responses only
       if {[HTTP::header value Content-Type] contains "text"}{
        STREAM::expression {@string@replacementstring@}
     Enable the stream filter for this response only
    log local0.emerg "Passed stream expression"
    STREAM::enable
    log local0.emerg  "variable $myVar is set now"
    }
    if {$myVar contains "string"}{
     Set Cookie value value to 'string' found by the Stream filter 
        log local0.emerg "Setting new persist Cookie"
    HTTP::cookie insert name "myCookie" value $myVar path "/"
        log local0.emerg "Cookie Set and Inserted"
    }
    }

     

  • The context error:

     

    [command is not valid in current event context (HTTP_RESPONSE)] [STREAM::match]

     

     

    Regards,

     

     

    Comms
  • i got this error.

     

     

    Oct 3 02:56:08 local/tmm err tmm[4888]: 01220001:3: TCL error: myrule - can't read "myVar": no such variable while executing "if {$myVar contains "string"}{ Set Cookie value value to 'string' found by the Stream filter HTTP::cookie insert name "myCookie" value $my..."

     

     

    because HTTP_RESPONSE is triggered before STREAM_MATCHED, myVar is not available at that time.

     

     

    iRules Event Order by Colin

     

    http://devcentral.f5.com/Tutorials/TechTips/tabid/63/articleType/ArticleView/articleId/344/iRules-Event-Order.aspx

     

     

    thinking if there is a tricky way to achieve this. does anybody have any idea? interesting...
  • Hi Nitass,

     

     

    Thanks for checking it out.

     

    Yep I got that one too.

     

     

    Regards,

     

     

    Comms
  • As Nitass said, HTTP_RESPONSE is triggered when the HTTP response headers from the pool member are parsed. The stream filter is applied after this event. The response headers have already been unbuffered and sent to the client by STREAM_MATCHED.

     

     

    If you want to modify the headers based on the response payload, you'll need to have TMM buffer the response using HTTP::collect.

     

     

    http://devcentral.f5.com/wiki/iRules.http__collect.ashx

     

     

    Aaron
  • Hi Hoolio,

    I'm not quite sure how that works.

    I've taken another tact given the new insights herein.

    The new issue I'm having is my string replacement does not appear to be functioning, my redirect appears to remain unvaried

    When STREAM_MATCHED {
        Insert  $myVar to the URI component of the HREF following 
        the junction /Junction/ for subsequent ingress processing
        set myVar [string tolower [getfield [STREAM::match] "." 1]]
        STREAM::replace  "external.domain.name/Junction/$myVar/"
    }when HTTP_REQUEST {
        Disable the stream filter for all requests via VS
        STREAM::disable
    
        Check URI for part of myVar (nodename01 to nodename19)
        if {[HTTP::uri] contains "nodename"}{
        set myVarCookie [getfield [HTTP::uri] "/" 3]
                
           Set & Insert Cookie for processing
           HTTP::cookie insert name "EV" value $myVar path "/"
     
           Redirect client for processing by the Internal VS
           ideally the preceding / needs to be removed after myVar as well
           HTTP::redirect [string map {$myVar ""} [HTTP::uri]]
     
        }
    }
     
    when HTTP_RESPONSE {
       Disable the stream filter by default
       STREAM::disable
     
         Enable the stream filter for text responses only
        if {[HTTP::header value Content-Type] contains "text"}{
     
            Find the value I want to change, but manage change in STREAM_MATCHED
            STREAM::expression {@string@@}
     
            Enable the stream filter for this response only
            STREAM::enable
        }
      
    } 
  • What are you trying to do? When you say it's not working, what is or isn't happening?

     

     

    Inserting a cookie and then sending a redirect in HTTP_REQUEST isn't going to work. In HTTP_REQUEST, the HTTP::cookie insert will insert a cookie in the request proxied to the pool member. If you redirect the request, that redirect won't have the cookie set. If you want to insert a cookie in a redirect response, you can use HTTP::respond:

     

     

    http://devcentral.f5.com/wiki/iRules.http__respond.ashx

     

     

    Aaron
  • Thanks Hoolio, that makes sense.

     

    I deploy and test and report back.

     

     

    Cheers,

     

     

    Comms