Forum Discussion
The condition in which the HTTP::disable command is being called is after 3 if statements, any one of which (or potentially more) could be triggered. If you think of an iRule event and the code within it as sort of a bucket of aggregate values that get "dumped" at the end of the event parsing, then you can sort of see why the "too many redirect invocations" error is reported so frequently here in the forum. For example:
when HTTP_REQUEST {
set a 1
if { $a equals 1 } {
HTTP::redirect "somewhere"
}
if { $a < 2 } {
HTTP::redirect "somewhere else"
}
if { $a > 0 } {
HTTP::redirect "another place"
}
}
I know this isn't highly indicative of your code, but here to draw a point. All three conditions match. The variable a is 1, is less than 2, and is greater than 0. If you thought of this in strict procedural terms, you'd guess that the first condition would get triggered and that would be the end of it. But iRules don't always work that way. In this HTTP event, each relevant condition is going to be parsed, which fills a "bucket" with data to be handled at the end of the event. In this case 3 redirects go into the bucket and that's bad. So back to your code. The HTTP::disable command essentially says, "stop the HTTP filter". In the else clause where it's found, any one (or more) of the 3 conditions before it, each either attempting to perform an HTTP response, or replace payload, is going to conflict with the HTTP::disable command which gets called regardless. Perhaps a more appropriate thing to do would be to make sure only one of the conditions gets triggered:
if { not ( [findstr [HTTP::payload] "" ] eq "" ) } {
HTTP::respond 204 "Connection" "close"
log local0.info "[IP::client_addr]->[TCP::local_port] Filter_noserial matched"
} elseif { [findstr [HTTP::payload] "Router" ] ne "" } {
log local0.info "[IP::client_addr]->[TCP::local_port] ROUTER"
HTTP::payload replace 0 [HTTP::payload length] [string map -nocase "Router PRGAV4202N" [HTTP::payload]]
} elseif { [findstr [HTTP::payload] ">0.0.0.0" ] ne "" } {
log local0.info "[IP::client_addr]->[TCP::local_port] 0.0.0.0"
set client_ip [IP::client_addr]
} else {
HTTP::disable
}
Just a suggestion and not 100% certain what implications that has on your application, but at the very least it solves another potential conflict between the HTTP::respond and HTTP::payload replace commands. As far as whether or not it's needed, I'd say probably not. It's at the end of an else clause at the end of an HTTP_REQUEST_DATA event, which for all intents and purposes is probably already at the end of HTTP parsing.