Forum Discussion

xiangyang_zhang's avatar
xiangyang_zhang
Icon for Nimbostratus rankNimbostratus
Mar 13, 2006

Add "http://" in HTTP response

Hello, all

 

 

In some HTTP requests, protocol identifier 'http://' is not added. We would like to add "http://" in URL if it doesn't exist. I wrote two iRules for this purpose, neither of them can work. Help is needed !

 

 

Rule 1:

 

when HTTP_REQUEST {

 

if { not ([HTTP::uri] starts_with "http") }{

 

set newUri [concat ["http://"] [HTTP:uri]]

 

HTTP::uri newUri

 

}

 

}

 

 

Rule 2:

 

 

when HTTP_REQUEST {

 

if { not ([HTTP::uri] starts_with "http") }{

 

set newUri [concat ["http://"] [HTTP:uri]]

 

HTTP::header replace uri newUri

 

}

 

 

}
  • The protocol is not part of the HTTP spec and is definitely not part of the URI.

     

     

    Here's a link to the spec if you have any questions:

     

     

    http://www.w3.org/Protocols/HTTP/HTTP2.html

     

    Click here

     

     

    Here are the entire contents for the following url request "http://somehost/foo/bar".

     

     

    GET /foo/bar HTTP/1.1

     

    Host: somehost

     

    User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.1) Gecko/20060111 Firefox/1.5.0.1

     

    Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5

     

    Accept-Language: en-us,en;q=0.5

     

    Accept-Encoding: gzip,deflate

     

    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7

     

    Keep-Alive: 300

     

    Connection: keep-alive

     

     

     

    As you'll see "http://" is nowhere to be seen. You can try to "guess" at the protocol by looking at the connecting port (80 for HTTP and 443 for HTTPS) but this can be overridden with your webserver if the webadmin so desires.

     

     

    If I would try to change the URI to prepend it with "http://" it the resulting post to the server would look like this:

     

     

    GET http:///foo/bar HTTP/1.1

     

    Host: somehost

     

    User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.1) Gecko/20060111 Firefox/1.5.0.1

     

    Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5

     

    Accept-Language: en-us,en;q=0.5

     

    Accept-Encoding: gzip,deflate

     

    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7

     

    Keep-Alive: 300

     

    Connection: keep-alive

     

     

     

    And the webserver will think the request was for "http://somehosthttp://foo/bar" which I guarantee is not what you want.

     

     

    -Joe
  • Joe, thanks for your thoroughly instruction.

     

     

    Sorry for not telling all of info. Actually we are using WAP2 protocol, the http:// can be see in the header. Here is one example. What do you think then ?

     

     

    GET http://192.168.200.10/test/lan/Browsing/1-Context_browsing/page1.html HTTP/1.1\r\n

     

    Cache-Control: no-cache\r\n

     

    Pragma: no-cache\r\n

     

    Host: 192.168.200.10\r\n

     

    Accept: text/html, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/css, multipart/mixed, text/vnd.wap.wml, application/vnd.wap.wmlc, application/vnd.wap.wmlscriptc, application/java-archive, application/java, application/x-java-

     

    Accept-Charset: iso-8859-1, utf-8, iso-10646-ucs-2; q=0.6\r\n

     

    Accept-Language: en\r\n

     

    User-Agent: Nokia6680/1.0 (3.04.35) SymbianOS/8.0 Series60/2.6 Profile/MIDP-2.0 Configuration/CLDC-1.1\r\n

     

    Via: 1.1\r\n
  • Ok, then your first rule should work, with a few modifications

     

     

    when HTTP_REQUEST {
      if { not ([HTTP::uri] starts_with "http") } {
        HTTP::uri "http://[HTTP::uri]"
      }
    }

     

     

    The TCL concat command concatenates two lists and the resulting value will be space delimited. Also, enclosing the "http://" in brackets should result in a runtime error because you are telling the code to run the "http://" command which doesn't exist.

     

     

    I've just avoided the overhead of the temporary variable and created the concatenated string directly in the HTTP::uri command statement.

     

     

    If this still doesn't work, then I'd suggest throwing some log statements in to verify that the "if" condition is met and that the "HTTP::uri" command is actaully getting called. If that is happening and you still aren't seeing the correct GET request on the backend server, then you'll probably have to contact F5 Technical Support to get further assitance.

     

     

    -Joe
  • It works perfectly. Thanks for help.

     

     

    One more issue. Because in our solution, over 95% of request are HTTP request, the rest of 5% are secure HTTP ( https) request. I think that alteernative 1 is more efficient than alternative 2. What is your opinion ?

     

     

    Alternative 1:

     

     

    if { not ([HTTP::uri] starts_with "http://") } {

     

    if { not ([HTTP::uri] starts_with "https://") } {

     

    HTTP::uri "http://[HTTP::uri]"

     

    }

     

    }

     

     

    Alternative 2:

     

     

    if { (not ([HTTP::uri] starts_with "http://")) and (not ([HTTP::uri] starts_with "https://"))} {

     

    HTTP::uri "http://[HTTP::uri]"

     

    }

     

     

  • Option 1 should work fine. Are you terminating the HTTPS traffic on the BIG-IP? If not, then there is no way to dig into the payload to determine the URI.

     

     

    -Joe