Forum Discussion
smp_86112
Cirrostratus
Feb 08, 2008STREAM::replace
I'm trying to write a simple iRule using a STREAM profile on an LTM running 9.1.2. According to the iRules wiki, the STREAM::replace was introduced in 9.0.0. However this simple iRule generates the er...
hoolio
Cirrostratus
Feb 12, 2008No warranty on this, but it worked in tests I tried. I tested by using a few different 'find regexes' and replacement strings. I tested to see that variable length matches were replaced correctly. Note that I only tested with a single global replacement string. The rule would need to be tweaked if you want to dynamically set the replacement text per response.
I tried to add comments to help you follow. There is an exorbitant amount of debug logging which will hopefully help. You could remove this altogether once you're done testing.
when RULE_INIT {
Log debug messages to /var/log/ltm? 1=yes, 0=no.
set ::collect_debug 1
A regular expression which describes what strings to replace (wrap the regex in curly braces).
set ::find_regex {about:blank}
set ::find_regex {[a-zA-Z]+}
set ::find_regex {[0-9]+}
The string to insert in replacement of the matched string(s)
set ::replacement_string "abc"
set ::replacement_string "x"
}
when HTTP_REQUEST {
Don't allow response data to be chunked
if { [HTTP::version] eq "1.1" } {
Check if this is a keep alive connection
if { [HTTP::header is_keepalive] } {
Replace the Connection header with Keep-Alive
HTTP::header replace "Connection" "Keep-Alive"
}
Set the serverside version to 1.0
HTTP::version "1.0"
}
}
when HTTP_RESPONSE {
Only check responses that are a javascript content type
if {[HTTP::header "Content-Type"] eq "application/x-javascript"} {
if {$::collect_debug}{log local0. "Received javascript response"}
Get the content length to collect
if { [HTTP::header exists "Content-Length"] } {
set content_length [HTTP::header "Content-Length"]
} else {
set content_length 1000000000
}
if { $content_length > 0 } {
if {$::collect_debug}{log local0. "Collecting $content_length"}
Collect the content
HTTP::collect $content_length
}
}
}
when HTTP_RESPONSE_DATA {
if {$::collect_debug}{log local0. "original payload: [HTTP::payload]"}
Find all the match strings in one pass (-indices saves the start and end index of each match to a list)
set match_indices [regexp -all -inline -indices $::find_regex [HTTP::payload]]
if {$::collect_debug}{log local0. "match_indices = $match_indices"}
Initialize a variable to track the offset of the match
set match_offset_len 0
Loop through the indices and replace the matching strings with the replacement string
foreach match_index $match_indices {
Take the first match's start index and adjust it if the payload has already been changed by a previous match
set match_start [expr [lindex $match_index 0] - $match_offset_len]
if {$::collect_debug}{log local0. "match_start = $match_start"}
Take the first match's end index and adjust it if the payload has already been changed by a previous match
set match_end [expr [lindex $match_index 1] - $match_offset_len + 1]
if {$::collect_debug}{log local0. "match_end = $match_end"}
Calculate the length of the match
set match_len [expr $match_end - $match_start]
if {$::collect_debug}{log local0. "match_len = $match_len"}
Calculate the length of the offset based on the past offset plus the difference between the current match and the replacement string
set match_offset_len [expr $match_offset_len + $match_len - [string length $::replacement_string]]
if {$::collect_debug}{log local0. "match_offset_len = $match_offset_len"}
For debug purposes, save and log the string which was matched
set match_string [string range [HTTP::payload] $match_start [expr $match_end - 1]]
if {$::collect_debug}{log local0. "match string = $match_string"}
Replace the match with the replacement string
HTTP::payload replace $match_start $match_len $::replacement_string
Log the updated payload
if {$::collect_debug}{log local0. "updated payload: [HTTP::payload]"}
}
}
Aaron
Recent Discussions
Related Content
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects