Forum Discussion

yaoxu_11146's avatar
yaoxu_11146
Icon for Nimbostratus rankNimbostratus
Aug 01, 2008

is it possible to write an iRule redirecting http requrest based on URI, but doesn't require http/fasthttp profile support?

we got a painful issue as describled in post http://devcentral.f5.com/Default.aspx?tabid=53&forumid=5&postid=26481&view=topic

 

In short, we need to do http request redirection based on URI, however we can't use neither of http or fasthttp profile. by default, http or fasthttp profile is required for a iRule as below:

 

 

when HTTP_REQUEST {

 

if {[string tolower [HTTP::uri]] starts_with "/XXXXX"} {

 

pool Pool_XXXXX

 

} elseif {[string toupper [HTTP::uri]] starts_with "/YYYYY"} {

 

pool Pool_YYYYY

 

} else {

 

pool Pool_WWWWW

 

}

 

}

 

 

so, is it possible to write an iRule redirecting http requrest based on URI, but doesn't require http/fasthttp profile support?

6 Replies

  • spark_86682's avatar
    spark_86682
    Historic F5 Account
    You could do something close with just a TCP profile. Something like:

     
     when CLIENT_ACCEPTED { 
       TCP::collect 
     } 
     when CLIENT_DATA { 
       set idx [string first " HTTP/1." [TCP::payload]] 
       if { $idx < 0 } { 
         if { [TCP::payload length] > 2048 } { 
            log local0. "ERROR! Could not find HTTP request in 2K! dropping..." 
            reject 
         } else { 
            Not enough data yet; collect more 
           TCP::collect 
         } 
         return 
       } 
       set request [string tolower [TCP::payload $idx]] 
       if { $request contains " /XXXXX" } { 
         pool Pool_XXXXX 
       } else { 
         pool Pool_WWWWW 
       } 
     } 
     

    I have not even tested the above to see if it compiles, much less works, but it should be a good starting point. Basically, since HTTP requests start with " HTTP/", this just collects enough TCP data to find that "HTTP/1." string, and calls everything before that the "request".

    Then, since you're doing starts_with and the request variable also contains the HTTP method, you'd need to do a contains " /XXXXX". In other words, that space in the string before the /XXXXX is important. If you prefer, you can (just after the string tolower line) find the first space in request and chop off all the characters up to it. Then, request should just have the URI and you can go back to starts_with.

    Makes sense?
  • unfortunately, after i applied this iRule to our site, the whole site is not accessible. I checked the iRule line by line, but failed to figure out while line blocked the access.

     

    the client just keeps connecting and then time out....
  • thanks for nmenant's reply, after adding 'tcp::release', users CAN be guided to the default pool pool_WWWWW, but the redirection to pool_XXXXX doesn't work, sorry i'm new to iRule, and can't figure out why...anybody could give me a hand?
  • Try throwing some logging in place:

     
     when CLIENT_ACCEPTED { 
       TCP::collect 
     } 
     when CLIENT_DATA { 
       set idx [string first " HTTP/1." [TCP::payload]] 
       if { $idx < 0 } { 
         if { [TCP::payload length] > 2048 } { 
            log local0. "ERROR! Could not find HTTP request in 2K! dropping..." 
            reject 
         } else { 
            Not enough data yet; collect more 
           TCP::collect 
         } 
         return 
       } 
       set request [string tolower [TCP::payload $idx]] 
       log local0. "Got request: $request" 
       if { $request contains " /XXXXX" } { 
         log local0. "Sending to Pool_XXXXX" 
         pool Pool_XXXXX 
       } else { 
         log local0. "Sending to Pool_WWWWW" 
         pool Pool_WWWWW 
       } 
     } 
     

    This will log the each request right before checking it, so you can see if it you're getting what you expect.

    One thing that I can think of that might be happening: the request is made all lowercase, so make sure your " /XXXXX" value in the if statement is also all lowercase.