A few suggestions:
1. Avoid trying to replace the string in binary content. You can check if the response content type starts with text before trying to perform the replacement:
if {[HTTP::header "Content-Type"] starts_with "text"}
2. Limit the collection amount to 1Mb. See SOL6578 (
Click here) and this post (
Click here) for details.
3. Consider disabling HTTP 1.1 on the server side connection if you want to prevent the server from sending chunked responses (which won't have a content length). See the Credit Card Scrubber iRule for an example (
Click here😞
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"
}
}
4. I'm not sure whether it would work or not, but I think using string map would theoretically be more efficient than a regex:
regsub -all "/eTime/" [HTTP::payload] "/be/eTime/" newdata
->
set newdata [string map {/eTime/ /be/eTime/} [HTTP::payload]]
I'm not sure if string map munges the content though, so if you try this double check the resulting HTML.
If you still see the out of bounds error, can you post the current iRule and let us know if the error happens on every request or just some?
Thanks,
Aaron
when HTTP_REQUEST {
Prevent the server from sending a compressed response
remove the compression offerings from the client
HTTP::header remove "Accept-Encoding"
Don't allow data to be chunked
if { [HTTP::version] eq "1.1" } {
Force downgrade to HTTP 1.0, but still allow keep-alive connections.
Since 1.1 is keep-alive by default, and 1.0 isn't,
we need make sure the headers reflect the keep-alive status.
Check if this is a keep alive connection
if { [HTTP::header is_keepalive] } {
Replace the connection header value with "Keep-Alive"
HTTP::header replace "Connection" "Keep-Alive"
}
Set server side request version to 1.0
This forces the server to respond without chunking
HTTP::version "1.0"
}
}
when HTTP_RESPONSE {
Check if it's a text response
if {[HTTP::header "Content-Type"] starts_with "text"}{
Determine how much content to collect (no more than 1Mb)
if {[HTTP::header exists "Content-Length"] && [HTTP::header "Content-Length"] <= 1048576]}{
set content_length [HTTP::header "Content-Length"]
} else {
Only collect the first 1Mb of the response content
This is a limitation described in SOL6578
set content_length 1048576
}
if { $content_length > 0 }{
Trigger collection of the payload
HTTP::collect $content_length
log local0. "[IP::client_addr]:[TCP::client_port]: Collecting content: $content_length"
}
}
}
when HTTP_RESPONSE_DATA {
log local0. "[IP::client_addr]:[TCP::client_port]: Original payload: [HTTP::payload]"
Replace /eTime/ with /be/eTime/ in the payload. Try using string map. Else use regsub.
regsub -all "/eTime/" [HTTP::payload] "/be/eTime/" newdata
set newdata [string map {/eTime/ /be/eTime/} [HTTP::payload]]
log local0. "[IP::client_addr]:[TCP::client_port]: Modified payload: [HTTP::payload]"
HTTP::payload replace 0 $content_length $newdata
}