Forum Discussion

sysop_182859's avatar
sysop_182859
Icon for Nimbostratus rankNimbostratus
Feb 23, 2016

URI rewrite based on chosen pool member

The issue is I have servers behind the F5 that only listen on a specific uri. For site.com/login (incoming from users), there are say 3 servers that listen for the following: (server1) site.com/one, (server2) site.com/two, and (server3) site.com/three. My understanding is I can use HTTP_REQUEST_SEND but I haven't been able to put together the pieces. I'm pretty green when it comes to irules unfortunately.

 

I'd like to take an incoming request for site.com and change it to any one of those after the load balancing has occurred. From searching around I found a pretty good example, but I can't seem to figure out how to change what they have in there (host header) to the uri only.

 

Here's the link to what I've been reading: https://devcentral.f5.com/questions/rewrite-url-based-on-selected-node-for-load-balancing

 

Essentially this is all I need, but instead of the entire url, just change the uri. Seems like I could use the if/then logic for this - if lb chose server1, rewrite uri to /one and so forth.

 

Many thanks in advance. I'll keep digging around and trying things in the meantime.

 

17 Replies

  • JamesSevedge_23's avatar
    JamesSevedge_23
    Historic F5 Account

    Based on your question it seems like you are trying to receive requests from users at site.com/login and if it gets load balanced to server 1 changed the uri to be site.com/one, and site.com/two for server 2 etc.. Is that correct? How come each server can't have /login as the URI? Or at least one uri the same for all servers such as "/internallogin"? If that is the case the below iRule should work for simple redirection.

     

    when HTTP_REQUEST {

     

    if {[HTTP::uri] contains "/login"} {

     

    HTTP::uri /internallogin

     

    pool /Common/poolname

     

    }

     

    }

     

    • JamesSevedge_23's avatar
      JamesSevedge_23
      Historic F5 Account
      Although you could try something like the iRule below to accomplish the URI rewrite. For HTTP_RESPONSE you may need to rewrite it back to /login though using "when HTTP_RESPONSE". when HTTP_REQUEST_SEND { clientside { switch [LB::server addr] { "1.1.1.1" { HTTP::uri /one } "1.1.1.2" { HTTP::uri /two } "1.1.1.3" { HTTP::uri /three } } } }
    • sysop_182859's avatar
      sysop_182859
      Icon for Nimbostratus rankNimbostratus
      I wish the backend servers would function like every other web server I've seen! The issue with that code though is the user will always come in with /login and would always be changed to /internallogin before a load balanced decision is made. In that case a user would always be sent to a particular pool with, at least from what I'm thinking, wouldn't change. Unless there was some sort of loop or check to see if a cookie is present maybe. I figured it would be easier to change the uri destined to the server after LTM has already made a decision, then depending on the server it chose use the appropriate uri. Additionally, if possible I'd like for the user to not see what is happening behind the scenes. It isn't really a security concern necessarily, but I think it would be cleaner if they didn't see the change. What you state initially is exactly what I'm looking for.
    • JamesSevedge_23's avatar
      JamesSevedge_23
      Historic F5 Account
      I would suggest the iRule I mentioned in my follow up comment then to rewrite the request based on lb decision made. I copied it again below. Just keep in mind you will need to rewrite the reponse coming back to fulfill your requirement that the user always think it is /login. The way to rewrite that would be to use the "when HTTP_RESPONSE" and then run the HTTP::uri command and change it back to /login if the response uri equals /one, /two or /three.

       

      Referencing this... https://clouddocs.f5.com/api/irules/LB__server.html

       

       

      when HTTP_REQUEST_SEND { clientside { switch [LB::server addr] { "1.1.1.1" { HTTP::uri /one } "1.1.1.2" { HTTP::uri /two } "1.1.1.3" { HTTP::uri /three } } } }
  • Hi Sysop,

    you may try the

    [getfield [LB::server addr] "%" 1]
    syntax to strip the route domain before comparsion. Alternatively compare
    [LB::server addr]
    with "
    10.80.9.113%1
    ", "
    10.80.9.94%1
    " or "
    10.80.9.104%1
    "

    when HTTP_REQUEST_SEND { 
        clientside {
            if { ([HTTP::uri] equals "/") } then { 
                switch -exact -- [getfield [LB::server addr] % 1] {
                    "10.80.9.113" { 
                        HTTP::uri "[HTTP::uri]rp"
                        log local0. "[HTTP::uri]"
                         if {$static::rewrite_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: HTTP uri path rewritten with rp"}
                    }
                    "10.80.9.94" { 
                        HTTP::uri "[HTTP::uri]rp1"
                        log local0. "[HTTP::uri]"
                         if {$static::rewrite_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: HTTP uri path rewritten with rp1"}
                    }
                    "10.80.9.104" { 
                        HTTP::uri "[HTTP::uri]rp2"
                        log local0. "[HTTP::uri]"
                         if {$static::rewrite_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: HTTP uri path rewritten with rp2"}
    
                    }
                }
            }
        }
    }
    

    Note: Change a little bit the order of your

    [if]
    and
    [switch]
    nestings to optimize the performance.

    Cheers, Kai