Forum Discussion

Greg_91698's avatar
Greg_91698
Icon for Nimbostratus rankNimbostratus
Mar 09, 2011

iRule only runs once

I have a BigIP 3400 running BIG-IP 9.4.8 Build 355.0 Final. I am trying to do some payload replacement. I contacted tech support and they told me to ask here. I would have thought they would know the answer. I first tried using a Stream Profile to do a simple replace of www.xyz.com with www3.xyz.com. The home page would load, but any links off the home page would only load a finite amount of data. Very frustrating. So, I decided to write an iRule. After some research I came up with the following:

 

 

when HTTP_REQUEST {

 

Don't allow data to be chunked

 

if { [HTTP::version] eq "1.1" } {

 

if { [HTTP::header is_keepalive] } {

 

HTTP::header replace "Connection" "Keep-Alive"

 

}

 

HTTP::version "1.0"

 

}

 

}

 

 

when HTTP_RESPONSE {

 

First, check to see if there's a Content-Length header

 

if {[info exists [HTTP::header Content-Length]] } {

 

If there is, we'll collect that much data

 

set clen [HTTP::header "Content-Length"]

 

} else {

 

Otherwise we collect the max

 

set clen 4294967295

 

}

 

 

if { $clen > 0 } {

 

HTTP::collect $clen

 

}

 

}

 

 

 

when HTTP_RESPONSE_DATA {

 

 

set find "www.xyz.com"

 

set replace "www3.xyz.com"

 

set payload [HTTP::payload]

 

log local0. "Test"

 

if {[regsub -all $find $payload $replace new_response] > 0} {

 

log local0. "Replacing www with www3."

 

HTTP::payload replace 0 [HTTP::payload length] $new_response

 

}

 

HTTP::release

 

}

 

 

 

 

This rule ONLY fires 1 time. Any subsequent refreshes or links I follow result in the rule not matching again. When I say the rule only fires 1 time the log entry of "Test" only shows up 1 time. I have to uninstall the iRule and then put it back to get it to work again. Like I said, I've asked Tech Support, but they were no help at all. Could someone please point me in the right direction? Thank you.

 

8 Replies

  • clazba's avatar
    clazba
    Icon for Nimbostratus rankNimbostratus
    Hi,

    You should be able to achieve this relatively easily using the STREAM::replace command. Have a look at the example below.

    
    when HTTP_REQUEST {
     Collects the entire payload as per content lenght 
    HTTP::collect [HTTP::header Content-Length]
    }
    
    when HTTP_REQUEST_DATA 
     Sets var to string 
    set string_to_find [findstr [HTTP::payload] TAG  4 <]
    log local0. "String $string_to_find identified in Request payload"
     Release payload
    HTTP::release
    }
    
    when HTTP_RESPONSE {      
     Disable the stream filter by default      
        STREAM::disable       
     You can use strings or Regexs to match string (this one matches email addresses)
    STREAM::expression {@[a-z0-9._%+-]+\@[a-z0-9.-]+\.[a-z]{2,6}@@}  
     Reenables the stream filter  
        STREAM::enable    
        }  
    
        when STREAM_MATCHED {    
     Sets data to replace
    set data_to_replace "something"
         Replaces string with var    
    STREAM::replace $data_to_replace   
        }
    

    Cheers,

    Claud

  • Hi Greg,

    Sorry to hear that you haven't been able to get concrete help with this yet. As Claud said, I would actually suggest you go back to the stream profile option and use a STREAM::expression based iRule to do this replacement in the HTTP response payloads.

    http://devcentral.f5.com/wiki/default.aspx/iRules/stream__expression

    You don't need to do the HTTP request payload collection in his example. But the response stream profile config should work well:

    
     Example which replaces http:// with https:// in response content
     Prevents server compression in responses
    when HTTP_REQUEST {
    
        Disable the stream filter for all requests
       STREAM::disable
    
        LTM does not uncompress response content, so if the server has compression enabled
        and it cannot be disabled on the server, we can prevent the server from 
        sending a compressed response by removing the compression offerings from the client
       HTTP::header remove "Accept-Encoding"
    }
    when HTTP_RESPONSE {
    
        Check if response type is text
       if {[HTTP::header value Content-Type] contains "text"}{
    
           Replace www.xyz.com with www3.xyz.com
          STREAM::expression {@www\.xyz\.com@www3.xyz.com@}
    
           Enable the stream filter for this response only
          STREAM::enable
       }
    }
    

    Aaron
  • Thanks for the help. I'll look into the STREAM::expression function. I was basing my iRule off of some of the examples found here on DevCentral, but they all used HTTP::payload. I'll let you know what I come up with. Thanks again.
  • Ok, the stream replace irule is doing the exact same thing the Stream Profile did. You can see what I mean by going to www3.msstate.edu and then go to www3.msstate.edu/president/
  • Do you have a custom HTTP profile with response chunking set to rechunk configured on the virtual server?

     

     

    Aaron
  • It's inheriting from the default http profile. It's set to "preserve".
  • Posted By hoolio on 03/10/2011 02:30 PM

     

    Do you have a custom HTTP profile with response chunking set to rechunk configured on the virtual server?

     

     

    Aaron

     

    Ok, this made me look at the http profile. I changed the Response Chunking to "selective". That fixed it. I then scrapped the iRule and and just used the Stream Profile. Works like a champ now. Thanks everyone for all of your help. This community rocks!

     

  • I'd still use the iRule as it's more efficient to only apply the stream filter to text responses. When just using a stream profile, the stream filter is applied to all request and response payloads. So you can get errant matches on request payloads and waste resources on non-text replies with just a stream profile.

     

     

    Aaron