Forum Discussion

krelm_52303's avatar
krelm_52303
Icon for Nimbostratus rankNimbostratus
Nov 20, 2008

Changing HTTP Header Host port

Am receiving http requests on a high port (55555) and need to remove this in the header for all requests (so it sends on as port 80).

 

 

For example...

 

 

Host: www.google.com:55555 change to Host: www.google.com

 

Host: www.msn.com:55555 change to Host: www.msn.com

 

 

I don't know what all the destinations will be, but need to strip of the 55555 port number from each. Thankfully, I we don't need to rewrite any payload traffic, just this header.

 

 

What is the most resource efficient way of achieving this with an irule?

 

 

TIA

 

 

5 Replies

  • Hi there,

    You can strip out anything after the : in the host header using the getfield command (Click here) or using scan in an iRule:

      
      when HTTP_REQUEST {  
        
          Replace host header value with everything before the colon  
         HTTP::header replace Host "[getfield [HTTP::host] : 1]"  
        
         log local0. "[IP::client_addr]:[TCP::client_port]: Replace original host [HTTP::host] with [getfield [HTTP::host] : 1]"  
      }  
      

    If the requests won't always have a port, you could check to see if the host header value contains a colon before replacing the value.

      
      when HTTP_REQUEST {  
        
          Check if host value has a colon  
         if {[HTTP::host] contains ":"}{  
        
             Replace host header value with everything before the colon  
            HTTP::header replace Host "[getfield [HTTP::host] : 1]"  
        
         log local0. "[IP::client_addr]:[TCP::client_port]: Replace original host [HTTP::host] with [getfield [HTTP::host] : 1]"  
         }  
      }  
      

    Here is an example using scan (Click here😞

      
      when HTTP_REQUEST {  
        
          Scan the host header value. Save the results to $host and $port if there is a colon in the header value  
         if {[scan [HTTP::host] {%[a-zA-Z_.-]:%d} host port] == 2}{  
        
            HTTP::header replace Host $host  
         }  
      }  
      

    I'm not sure whether scan would be more efficient than getfield. You could use the timing command to test this:

    Timing command Click here, Timing article Click here

    Aaron
  • Thanks Aaron - great info as ever!

     

     

    I used the first example, and the Host header is being forwarded correctly without the port, so all good there. However, the Request URI needs to have the port stripped out too. How would I do this as well?

     

     

    Thanks again.

     

     

  • Is the app including the port number in redirects? If so, you can try rewriting the redirects using the HTTP profile option. Or you can use an iRule:

     
     when HTTP_RESPONSE { 
      
         Check if response is a redirect 
        if {[HTTP::is_redirect]}{ 
      
            Replace :55555/ with / in the Location header 
           HTTP::header replace Location [string map {:55555/ /} [HTTP::header value Location]] 
        } 
     } 
     

    If the port isn't in the Location header, can you explain where you're seeing it?

    Aaron
  • Here's a version that is working for us (changing the Request Host header and URI), but hoping there's an easier way to modify the URI?

     

     

    when HTTP_REQUEST {

     

    Check if host value has a colon

     

    if {[HTTP::host] contains ":"}{

     

    log local0. "URI: [HTTP::uri]"

     

     

    set find ":55555"

     

    set replace ""

     

    set uri_old [HTTP::uri]

     

    regsub -all $find $uri_old $replace new_uri

     

    HTTP::uri $new_uri

     

     

    log local0. "NEW URI: [HTTP::uri]"

     

    Replace host header value with everything before the colon

     

    set new_host [getfield [HTTP::host] ":" 1]

     

     

    HTTP::header replace "Host" $new_host

     

    log local0. "[IP::client_addr]:[TCP::client_port]: Replace original host [HTTP::host] with [getfield [HTTP::host] ":" 1]"

     

    }

     

    }

     

     

    Also, as you suggest, it looks like we'll need to modify the HTTP_Response Location header + any other references to objects in the HTTP_Response payload. May need to look at this...

     

    http://devcentral.f5.com/weblogs/Joe/archive/2005/07/27/1398.aspx

     

     

    Cheers.
  • Can you post some anonymized samples of the URI's you want to rewrite? Is the client using an absolute URI? Something like this?

     

     

    GET http://www.w3.org:55555/pub/WWW/TheProject.html HTTP/1.1

     

    User-Agent: ...

     

     

    If so, you could use string map instead of regsub. The string function would be more efficient than a regex.

     

     

    HTTP::uri [string map {:55555/ /} [HTTP::uri]]

     

     

    If you also need to rewrite the port in response content, you could use a stream filter and STREAM::expression based iRule. This would be more efficient than collecting the response content and performing regex operations on it. You can check the STREAM::expression wiki page (Click here) for examples.

     

     

    Aaron