Forum Discussion
Help needed: HTTP::respond does not add headers
I am struggling with HTTP::respond and adding headers.
This is an outline of what I am trying to do:
when HTTP_RESPONSE {
Save response-headers for later use
set headers ""
foreach aHeader [HTTP::header names] {
set headers [concat $headers $aHeader [HTTP::header value $aHeader]]
}
log local0. "Headers Saved: $headers"
Fetch "x-http-statuscode" for later use
if {[HTTP::header exists "x-http-statuscode"]} {
set xhttpstatuscode [lindex [HTTP::header values x-http-statuscode] 0]
}
if {[HTTP::status] == 200 && [expr {$xhttpstatuscode != 200}]} {
HTTP::respond $xhttpstatuscode -version [HTTP::version] content [HTTP::payload] $headers
}
}
I can't get HTTP::repond to add the "original headers"!
Help is appreciated!
Hi Mats,
you have to use the [eval] command to allow the TCL interpreter to expand the $headers variable before executing the [HTTP::respond] command. Otherwise the collected headers storend in $headers will be counted just as a single parameter.
Warning: Special care must be taken if you use [eval]. The problem of this technique is, that the input may contain TCL syntax (e.g. [somecommand] and $variables) which may accedentially become executed by the [eval] command (aka. its comparable with SQL-Injection for TCL). In the best case this will lead to a broken TCP connection, but in the worst case could also crash your TMM core or even lead into a full compromise of your TMM/TCL environment.
You may take a look to the snipped below to get familar with the usage of [eval] and to learn a syntax how the header values can be securely collected and then passed to eval.
when HTTP_RESPONSE { if { ( [HTTP::header exists "x-http-statuscode"] ) and ( [HTTP::status] == 200 ) and ( [set xhttpstatuscode [lindex [HTTP::header values "x-http-statuscode"] 0]] != 200 ) } then { Save response-headers for later use set headers "" set x 0 foreach aHeader [HTTP::header names] { incr x set input_array(name_$x) $aHeader set input_array(value_$x) [HTTP::header value $aHeader] append headers "\$input_array(name_$x) \$input_array(value_$x) " Explanation: The names and values of your headers are getting temporary stored in a $input_array() variable. This technique makes sure, that the later use of [eval] never interprets the contained values as TCL syntax. This technique is comparable to a parameterised SQL query to counter SQL injections. } log local0. "Headers Saved: $headers" eval "HTTP::respond $xhttpstatuscode -version [HTTP::version] content {[HTTP::payload]} $headers" Explanation: [eval] uses two passes in its execution, the first pass will concentate [command]s and $variables into eval's input string. And the second pass will execute the input string as TCL code and concentate [command]s and $variables a second time. Raw TCL syntax: eval "HTTP::respond $xhttpstatuscode -version [HTTP::version] content {[HTTP::payload]} $headers" First pass substitution result: eval "HTTP::respond 404 -version 1.1 content [HTTP::payload] $input_array(name_1) $input_array(value_1) $input_array(name_2) $input_array(value_2)" Second pass code execution: HTTP::respond 404 -version 1.1 content {...} {MyHeader1} {MyHeaderValue1} {EvilHeader} {Evil\[InsertTCLCodeHere\]HeaderValue} } }
Additional Note: The [HTTP::payload] command will not output the response payload unless [HTTP::collect] is called and the HTTP_RESPONSE_DATA event is raised.
*Update: Modified my previous post to include the parameterised eval syntax.
Cheers, Kai
Recent Discussions
Related Content
* 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