Forum Discussion

James_Thomson's avatar
Feb 02, 2015

How can I reorder HTTP headers?

I want to insert an HTTP header into the current list of HTTP headers, but I need it to be the first HTTP header in the list, before the Host, Content-Type and Content-Length. Using the standard HTTP::header insert, puts it at the. Since there are no commands to insert it into a specific spot, I figure I need to create a variable with each HTTP::header name=value pair and then delete them all, then start adding one by one starting with my custom one.

Either way, I have been trying foreach loops and while loops and can't figure out how to use a dynamic variable that increments as I iterate through the number of inbound HTTP headers. I'm currently trying something like this:

set y 0
set hc [HTTP::header count]
while {$y <= $hc} {
log local0. "y=$y"
set v "v-$y"
log local0. "v=$v"
set na "[HTTP::header at $y]"
set va "[HTTP::header value $na]"
log local0. "na=$na va=$va"
set $v "$na $va"
log local0. "v=$v"
incr y
}

I'm sure I'm missing some tcl savvy so I'll take any suggestions you have.

  • Hi James,

     

    You can use a for loop and grab the HTTP::header count (but I would suggest looking at the Wiki Entry for HTTP::header. It was reported that at one time it was zero based, but was fixed in v9.4.8 and v10.x.x).

     

    Like this in C, but you will want to look up how to do it in TCL. for (i = 0, i < HTTP::header count; i++)

     

    Hope this helps.

     

  • Hi James,

     

    how about reading all header into an array, delete them, reorder and reinsert?

     

    Here is some sample code used to remove a specific cookie parameter out of response cookies.

     

    It needs to be rewritten to get fired in HTTP_REQUEST (you did not specify), get a list of all headers, delete them, insert the new one followed by all stored parameters.

     

    when HTTP_RESPONSE {
        if {[HTTP::header exists "Set-Cookie"]}{
            array set cookielist { }
            foreach cookievalue [HTTP::header values "Set-Cookie"] {
                set cookielist([getfield $cookievalue "=" 1]) [string map -nocase { "; HttpOnly" ""} $cookievalue]
                log local0. "serverside cookie: $cookievalue"
            }
            HTTP::header remove Set-Cookie
            foreach cookiename [array names cookielist] {
                 if { [info exists cookielist($cookiename)] } {
                     log local0. "clientside cookie: $cookielist($cookiename)"
                     HTTP::header insert Set-Cookie $cookielist($cookiename)
                 }
            }
        }
    }
    

    Thanks, Stephan

     

  • Hi James,

     

    you can give this one a try (perhaps you want to apply in HTTP_RESPONSE context), please.

     

    when HTTP_REQUEST {
         initialize array to store all headers
        array set header_list { }
    
         parse each header and store in array
        foreach header_name [HTTP::header names] {
            set header_list($header_name) [HTTP::header $header_name]
            log local0. "name: $header_name; value: $header_list($header_name)"
        }
    
         delete all headers
        foreach header_name [HTTP::header names] {
            HTTP::header remove $header_name
            log local0. "header removed: $header_name"
        }
    
         insert new custom header
        HTTP::header insert MyNewTestHeader MyNewTestHeaderValue
    
         insert all headers from array (append)
        foreach header_name [array names header_list] {
            HTTP::header insert $header_name $header_list($header_name)
            log local0. "header inserted: $header_name; value: $header_list($header_name)"
        }
    }
    

    Be careful with cookies, there may be multiple header instances and the code above does not really care about it.

     

    Thanks, Stephan