Forum Discussion
ukstin
Nimbostratus
Jun 09, 2008conditional redirect (404)
Hi people,
I´m trying to wrote a i-rule to redirect a 404 error based on the url. The i-rule I made is this one:
when HTTP_REQUEST {
set host [HTTP::host]
set url [HTTP::uri]
}
when HTTP_RESPONSE {
set status_code [HTTP::status]
if { $status_code equals 404 } {
if { $host contains "abcd" } {
HTTP::redirect "http://abcd.otherdomain.com/$url"
}
elseif { $host contains "efg" } {
HTTP::redirect "http://efg.otherdomain.com/$url"
}
else {
HTTP::redirect "http://anotherone.com/xyz.html"
}
}
}
it seens ok to me and it works almost every time, but sometimes I received the following error:
Jun 9 19:25:07 tmm tmm[1133]: 01220001:3: TCL error: Rule irule_redirect_404 - can't read "host": no such variable while executing "if { $host contains ..."
any ideas why the host variable doesn´t work sometimes?
4 Replies
- The_Bhattman
Nimbostratus
Looks like the variable can't be used in another part of the irule.
have you tried the followingwhen HTTP_REQUEST { set ::host [HTTP::host] set ::url [HTTP::uri] } when HTTP_RESPONSE { if { [HTTP::status] == 404 } { if { $::host contains "abcd" } { HTTP::redirect "http://abcd.otherdomain.com/$::url" } elseif { $::host contains "efg" } { HTTP::redirect "http://efg.otherdomain.com/$::url" } else { HTTP::redirect "http://anotherone.com/xyz.html" } } }
If you noticed I am changing your variable from local to global. I have not tested this, but give that a shot.
CB - Patrick_Chang_7Historic F5 AccountSome HTTP requests do not contain a host header. Therefore, [HTTP::host] will be empty. You could change the when HTTP_REQUEST logic to read the host from the first line of the raw HTTP::request if [HTTP::host] is an empty string. I would log the value of [HTTP::host] when you set the host variable, just to make sure though. You can remove the logging when the rule is fully debugged.
- hoolio
Cirrostratus
The host header is only required for HTTP 1.1. If a client sends an HTTP 1.0 (or even 0.9) request, the Host header value wouldn't necessarily be present, but regardless the $host variable should be set to a zero length string. I'm not sure how the runtime error could be triggered for $host not being defined, as it's set on every HTTP request (even if it's to a null value).
Using the rule below, I did some tests on 9.2.4 using netcat. In every test, checking if the $host value contained a string succeeded without a TCL error. Between this post and a related one on the ProxyPass rule (Click here), I'd suggest opening a case with F5 Support. It seems like this might be a bug.
As a workaround, you could add a check to see if $host exists before trying to check if it contains a string:when HTTP_REQUEST { set host [HTTP::host] set url [HTTP::uri] } when HTTP_RESPONSE { if { [HTTP::status] == 404 } { if {[info exists host]}{ if {$host contains "abcd" } { HTTP::redirect "http://abcd.otherdomain.com/$url" } elseif {[info exists host] && $host contains "efg" } { HTTP::redirect "http://efg.otherdomain.com/$url" } else { HTTP::redirect "http://anotherone.com/xyz.html" } } else { $host doesn't exist! log local0. "[IP::client_addr]:[TCP::client_port]: \$host was not set!?" } } }
Aaron
Example rule which saves the HTTP::host output and checks the value in HTTP_RESPONSE:when HTTP_REQUEST { set host [HTTP::host] log local0. "HTTP version: [HTTP::version], HTTP host: $host, HTTP uri: [HTTP::uri]" } when HTTP_RESPONSE { if { $host contains "www" } { log local0. "matched $host" } else { log local0. "didn't match $host" } }
Request with a Host header:
$ nc 192.168.101.40 80
GET /withhost HTTP/1.1
Connection: close
Host: www.example.com
Log output:
Rule log_http_host_rule : HTTP version: 1.1, HTTP host: www.example.com, HTTP uri: /withhost
Rule log_http_host_rule : matched www.example.com
Request without a Host header:
$ nc 192.168.101.40 80
GET /withouthost HTTP/1.0
Log output:
Rule log_http_host_rule : HTTP version: 1.0, HTTP host: , HTTP uri: /withouthost
Rule log_http_host_rule : didn't match
0.9 formatted request:
$ nc 192.168.101.40 80
GET /
Log output:
Rule log_http_host_rule : HTTP version: 0.9, HTTP host: , HTTP uri: /
Rule log_http_host_rule : didn't match
Request with a Host header, but nothing after the colon:
nc 192.168.101.40 80
GET / HTTP/1.0
Host:
Test: value
Log output:
Rule log_http_host_rule : HTTP version: 1.1, HTTP host: Connection: close, HTTP uri: /
Rule log_http_host_rule : didn't match Connection: close
This last one could be considered a bug as well. Apparently the HTTP parser doesn't stop parsing the Host header value at the line terminating CRLF if there isn't a value for the header.
'HTTP::header Host' seems to be more accurate:when HTTP_REQUEST { set http_host [HTTP::host] set http_header_host [HTTP::header Host] log local0. "HTTP version: [HTTP::version], HTTP host: $http_host, HTTP header Host: $http_header_host, HTTP uri: [HTTP::uri]" } when HTTP_RESPONSE { if { $http_host contains "www" } { log local0. "http_host matched $http_host" } else { log local0. "http_host didn't match $http_host" } if { $http_header_host contains "www" } { log local0. "http_header_host matched $http_header_host" } else { log local0. "http_header_host didn't match $http_header_host" } }
Request:
$ nc 192.168.101.40 80
GET / HTTP/1.0
Host:
Test: value
Log output shows HTTP::host errantly returns the next header name and value, while HTTP::header Host correctly returns nothing:
Rule log_http_host_rule : HTTP version: 1.0, HTTP host: Test: value, HTTP header Host: , HTTP uri: /
Rule log_http_host_rule : http_host didn't match Test: value
Rule log_http_host_rule : http_header_host didn't match - Andy_Herrman_22
Nimbostratus
Yea, this looks really similar to the ProxyPass issue from a couple days ago. They were setting a variable in HTTP_REQUEST but occasionally they'd get a runtime error accessing it in HTTP_RESPONSE.
I wonder if there's a bug or some weird situation where HTTP_RESPONSE is being triggered without a corresponding HTTP_REQUEST.
Out of curiosity, do you have OneConnect enabled?
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
