Forum Discussion

Russell_McGinni's avatar
Russell_McGinni
Icon for Nimbostratus rankNimbostratus
Feb 03, 2010

iRule to alter streamed response screwing up!

We use our F5 throughout all our environments, dev, qa and live (and beta). We have an iRule in place (as shown below) which is meant to find all occurances of www.blah.com and change it to qa1.blah.com. Additionally, if we have a content-type response that is text in some way, we essentially inject some js includes by replacing the "end body" tag with the js includes and then the "end body" tag.

 

 

It works pretty well, however we started noticing that it would inject the js includes into WebResource.AXD responses if that AXD file (which is just another js file) contained an "end body" tag somewhere. This is even though the AXD file is of content type application/x-javascript. From logging, we also noticed that for the AXD file request, we never get into the second "IF statement" in the HTTP_RESPONSE event.

 

 

So... how can this be!!!!

 

 

Russell McGinnis

 

 

when HTTP_REQUEST {

 

Save the URI so we can check it in the response

 

set uri [string tolower [HTTP::uri]]

 

set host [string tolower [HTTP::host]]

 

set repl "qa1"

 

}

 

 

when HTTP_RESPONSE {

 

if { [HTTP::status] eq "200" } {

 

Use a stream expression to replace content within the stream

 

IF... we are dealing with text content THEN

 

 

if {[HTTP::header value Content-Type] contains "text"} {

 

set stream_expression "@www.blah.com@$repl.blah.com@"

 

set stream_find ""

 

set stream_find_lower [string tolower $stream_find]

 

set stream_repl ""

 

set stream_repl_google_include "http://www.google-analytics.com/ga.js"

 

 

set InjectScript 1

 

log local0.debug "checking $uri"

 

switch -glob $uri {

 

"*.ashx*" -

 

"*.asmx*" -

 

"*.axd*" -

 

"*.js*" -

 

"*/player/html" {

 

set InjectScript 0

 

}

 

}

 

if { [TCP::server_port] == 443 }{

 

set InjectScript 0

 

set stream_repl_google_include "https://ssl.google-analytics.com/ga.js"

 

}

 

if { [HTTP::payload] contains "META HTTP-EQUIV=\"Refresh\""} {

 

set InjectScript 0

 

}

 

 

if {$InjectScript == 1} {

 

set include_js "infobarhandler.ashx"

 

 

append stream_repl ""

 

}

 

 

Google analytics for all text pages

 

append stream_repl ""

 

 

append stream_expression " @$stream_find@$stream_repl$stream_find@"

 

append stream_expression " @$stream_find_lower@$stream_repl$stream_find_lower@"

 

 

STREAM::disable

 

STREAM::expression $stream_expression

 

STREAM::enable

 

}

 

}

 

}

3 Replies

  • I believe the problem lies in the fact that you not disabling the STREAM profile for requests not matching your criteria. If a first request comes back that matches the content type you are disabling the profile, updating the expression and then enabling it. The profile will remain enabled for that virtual server on all subsequent requests with that given expression until you explicitly disable it or it is changed by a subsequent matching response.

     

     

    I would try moving the "STREAM::disable" to the first line in the HTTP_RESPONSE event and then only enable it when your match condition is reached.

     

     

    -Joe
  • When you call STREAM::enable it enables the stream filter until STREAM::disable is called or the connection is closed. So you want to disable the stream filter on each response by default. Then enable it for the specific responses you want to rewrite.

    Can you try this?

     
     when HTTP_REQUEST { 
         Save the URI so we can check it in the response 
        set uri [string tolower [HTTP::uri]] 
        set host [string tolower [HTTP::host]] 
        set repl "qa1" 
     } 
      
     when HTTP_RESPONSE { 
      
         Disable the stream filter by default 
        STREAM::disable 
      
        if { [HTTP::status] == 200 } { 
      
            Use a stream expression to replace content within the stream 
            IF... we are dealing with text content THEN 
           if {[HTTP::header value Content-Type] contains "text"} { 
              set stream_expression "@www.blah.com@$repl.blah.com@" 
              set stream_find "" 
              set stream_find_lower [string tolower $stream_find] 
              set stream_repl "" 
              set stream_repl_google_include "http://www.google-analytics.com/ga.js" 
      
              set InjectScript 1 
              log local0.debug "checking $uri" 
              switch -glob $uri { 
                 "*.ashx*" - 
                 "*.asmx*" - 
                 "*.axd*" - 
                 "*.js*" - 
                 "*/player/html" { 
                    set InjectScript 0 
                 } 
              } 
              if { [TCP::server_port] == 443 }{ 
                 set InjectScript 0 
                 set stream_repl_google_include "https://ssl.google-analytics.com/ga.js" 
              } 
              if { [HTTP::payload] contains "META HTTP-EQUIV=\"Refresh\""} { 
                 set InjectScript 0 
              } 
      
              if {$InjectScript == 1} { 
                 set include_js "infobarhandler.ashx" 
                 append stream_repl "" 
              } 
      
               Google analytics for all text pages 
              append stream_repl "" 
      
              append stream_expression " @$stream_find@$stream_repl$stream_find@" 
              append stream_expression " @$stream_find_lower@$stream_repl$stream_find_lower@" 
      
              STREAM::expression $stream_expression 
              STREAM::enable 
           } 
        } 
     } 
     

    Aaron
  • Thanks guys... that helped. Fixed the issue and helped me understand the "stream" a little better.