Forum Discussion
Adrian_Turcu_10
Nimbostratus
Oct 30, 2007Help With HTTP_RESPONSE
Hello Gurus
Could someone help me with a quick rule to replace a header in the response back to the client, please?
My problem is like follows: we have a poxi app (not proxy) and t...
hoolio
Cirrostratus
Oct 30, 2007A couple of notes/suggestions:
HTTP::method (Click here) won't return the protocol used for the request (HTTP or HTTPS). It will return the method used in the request (GET, HEAD, POST, etc).
If you want to determine whether to use HTTP or HTTPS in the Location header value, you can either assume it based on whether the rule is added to an HTTP or HTTPS virtual server, or for wildcard port virtual servers you can check the requested port (using TCP::local_port in the client side context).
The HTTP::host command will return what the client entered after the protocol (http:// or https://) and before the start of the URI (/path/to/file.txt) in the address bar of the browser. For example, if a client requested https://test.example.com:80/index.jsp?pageno=1, HTTP::host would return test.example.com:80. Most clients don't make requests which include the port number though. Unless the requested URL contained the port, splitting the HTTP::host value on a colon and taking the second field will not return anything.
If you want to replace a string within a string in TCL, you can use the string map command (http://www.hume.com/html84/mann/string.html). The format is: string map "find1 replace1 find2 replace2" original_string. If you're using literal strings for the find/replace, you can use {}'s instead of the ""'s.
You can test basic commands in the RULE_INIT event. This event is triggered when the rule is created or saved. You don't have to assign the rule to a virtual server even. You can check the /var/log/ltm log file for the log output. It can be an easy way to check string commands and others that are allowed in the RULE_INIT event. Here's an example:
when RULE_INIT {
save a sample string to the $::location_test variable
set ::location_test "http://127.0.0.1/path/to/file.txt"
save a sample HTTP host header value
set ::host_test "www.example.com"
log the value
log local0. "Sample Location header value: $::location_test"
replace the string "127.0.0.1" with the test host header value
log local0. "Updated string 1: [string map "127.0.0.1 $::host_test" $::location_test]"
replace the strings "http://" with "https://" and "127.0.0.1" with the test host header value
log local0. "Updated string 2: [string map "http:// https:// 127.0.0.1 $::host_test" $::location_test]"
}This logs the following:
Rule : Sample Location header value: http://127.0.0.1/path/to/file.txt
Rule : Updated string 1: http://www.example.com/path/to/file.txt
Rule : Updated string 2: https://www.example.com/path/to/file.txtBased on that, you can build an example to perform the actual replacement of the Location header in 3xx redirect responses coming from the pool members. This one checks the port the client made a request to. If it was 443, then any instance of http:// in the Location header will be replaced with https://. If the port wasn't 443, then only the 127.0.0.1 string is replaced.
when HTTP_REQUEST {
Save host (without the port if it's specified)
set shost [getfield [HTTP::host] ":" 1]
log local0. "Parsed Host header value: $shost"
}
when HTTP_RESPONSE {
check if response is a redirect (HTTP status of 3xx)
if { [HTTP::status] starts_with "3" } {
Save original Location value
set location_original [HTTP::header value Location]
log local0. "Original Location header value: $location_original"
Check if the port the request was made on was 443
if {[clientside {TCP::local_port}] == 443}{
Request was made to an SSL port, so replace 127.0.0.1 with the Host header value from the request
and replace http:// with https:// in the Location header value
set location_updated [string map "http:// https:// 127.0.0.1 $shost" $location_original]
log local0. "Updated Location header value for HTTP request: $location_updated"
Perform the actual header replacement
HTTP::header replace Location $location_updated
} else {
Request was made to an HTTP port, so just replace 127.0.0.1 with the Host header value from the request
set location_updated [string map "127.0.0.1 $shost" $location_original]
log local0. "Updated Location header value for HTTPS request: $location_updated"
Perform the actual header replacement
HTTP::header replace Location $location_updated
}
}
}This logs the following for an HTTP request followed by an HTTPS request:
: Parsed Host header value: 192.168.101.42
: Original Location header value: http://127.0.0.1/test/file.txt
: Updated Location header value for HTTP request: https://192.168.101.42/test/file.txt
: Parsed Host header value: 192.168.101.42
: Original Location header value: http://127.0.0.1/test/file.txt
: Updated Location header value for HTTPS request: http://192.168.101.42/test/file.txtThe above example uses extra variables so you can log the intermediate steps. It could be streamlined to remove the extra variables.
Hope this helps...
Aaron
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)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