Forum Discussion

gpoverland's avatar
gpoverland
Icon for Nimbostratus rankNimbostratus
Jul 08, 2008

IRule that rewrites URI based on Pool or PoolMember Selected

I am trying to create an Irule that selects to rewrite a URI based on which pool member is chosen. Why you ask, well this is to accomodate the slow migration from an older application to a newer application. The new application will require me to use Ratio Loadbalancing to slowly increase the load on the front end servers.. The second part, which is required, will depend on which pool member is selected in the associated pool.

 

 

Here is what I was thinking, but because how the request comes in and the order in which the F5's look at and process the request, I don't think this will work.. Any suggestions would be helpful.. Thanks

 

 

{IRULE}:

 

 

when LB_SELECTED {

 

if {[LB::server addr] eq "172.29.58.3" or "172.29.58.4"}

 

}

 

 

when HTTP_REQUEST {

 

if { [HTTP::uri] contains "/GSFO/GSFOPub" } {

 

HTTP::uri "/Async/CMReceive.ashx"

 

use pool b2b-iad1-test

 

}

 

elseif { [HTTP::uri] contains "/ERA/ERAPub" } {

 

HTTP::uri "/Async/ERAReceive.ashx"

 

use pool b2b-iad1-test

 

}

 

use pool b2b-iad1-test-legacy

 

}
  • Better yet.. will something like this work?

     

     

    when HTTP_REQUEST {

     

    if {[LB::server addr] eq "172.29.58.3" or "172.29.58.4"} {

     

    if { [HTTP::uri] contains "/GSFO/GSFOPub"} {

     

    HTTP::uri "/Async/CMReceive.ashx"

     

    use pool b2b-iad1-test

     

    }

     

    elseif { [HTTP::uri] contains "/ERA/ERAPub" } {

     

    HTTP::uri "/Async/ERAReceive.ashx"

     

    use pool b2b-iad1-test

     

    }

     

    }

     

    use pool b2b-iad1-test-legacy

     

    }
  • hoolio's avatar
    hoolio
    Icon for Cirrostratus rankCirrostratus
    You're on track. The issue is that HTTP_REQUEST is triggered when the HTTP request headers are parsed. The headers are parsed and then a pool member is selected by the LB_SELECTED event. For details on events, you can check the wiki page (Click here) and for an example of the order (Click here).

    You can modify the URI in the HTTP_REQUEST_SEND event using the clientside command. The clientside command is necessary to change the context from the server side to client side.

    I'm not sure what you're doing with the pool commands though, so I've left that part out. If you do really want to reselect a different pool once you determine the IP address of the server LTM picked the first time around, could you add some background?

     
     when HTTP_REQUEST_SEND { 
      
         Save the URI to avoid running this command multiple times. 
        set uri [clientside {HTTP::uri}] 
        log local0. "[IP::client_addr]:[TCP::client_port]: \$uri: $uri" 
      
        log local0. "[IP::client_addr]:[TCP::client_port]: selected server details: [LB::server]" 
      
         Check if the selected servfer is .3 or .4 
        if {[IP::addr [LB::server addr] equals 172.29.58.3] or [IP::addr [LB::server addr] equals 172.29.58.4]} { 
      
           log local0. "[IP::client_addr]:[TCP::client_port]: matched server check for .3 or .4" 
      
            Check if the URI contains the first string 
           if {$uri contains "/GSFO/GSFOPub"} { 
      
      
               Update the URI 
              clientside {HTTP::uri "/Async/CMReceive.ashx"} 
              log local0. "[IP::client_addr]:[TCP::client_port]: updated URI to /Async/CMReceive.ashx" 
      
            Check if the URI contains the second URI 
           } elseif {$uri contains "/ERA/ERAPub" }{ 
      
               Update the URI 
              clientside {HTTP::uri "/Async/ERAReceive.ashx"} 
              log local0. "[IP::client_addr]:[TCP::client_port]: updated URI to /Async/ERAReceive.ashx" 
      
           } else { 
                Take some default action? 
              log local0. "[IP::client_addr]:[TCP::client_port]: didn't match URI checks" 
           } 
        } 
     } 
     

    Aaron
  • I actually removed the pools.. couldn't figure out why I would identify them either.. As for the Irule.. Thanks I'll give it a try..

     

     

  • Trying to make this case insensitive... tried forcing the URI when it is stored to force it lower case, but for some reason its not working.. Is this the correct way to do this and what am I doing wrong?

     

     

     

     

     

    when HTTP_REQUEST_SEND {

     

     

    Save the URI to avoid running this command multiple times.

     

    set uri [clientside [string tolower {HTTP::uri}]]

     

    log local0. "[IP::client_addr]:[TCP::client_port]: \$uri: $uri"

     

     

    log local0. "[IP::client_addr]:[TCP::client_port]: selected server details: [LB::server]"

     

     

    Check if the selected server is .3 or .4

     

    if {[IP::addr [LB::server addr] equals 10.207.225.101] or [IP::addr [LB::server addr] equals 10.207.225.102] or [IP::addr [LB::server addr] equals 10.207.225.103]} {

     

     

    log local0. "[IP::client_addr]:[TCP::client_port]: matched server check for .3 or .4"

     

     

    Check if the URI contains the first string

     

    if {$uri contains "/gsfo/gsfopub"} {

     

     

    Update the URI

     

    clientside {HTTP::uri "/Async/CMReceive.ashx"}

     

    log local0. "[IP::client_addr]:[TCP::client_port]: updated URI to /Async/CMReceive.ashx"

     

     

    Check if the URI contains the second URI

     

    } elseif {$uri contains "/era/erapub" }{

     

     

    Update the URI

     

    clientside {HTTP::uri "/Async/ERAReceive.ashx"}

     

    log local0. "[IP::client_addr]:[TCP::client_port]: updated URI to /Async/ERAReceive.ashx"

     

     

    Check if the URI contains the third URI

     

    } elseif {$uri contains "/utilities/servconntest" }{

     

     

    Update the URI

     

    clientside {HTTP::uri "/Async/ServConnTest.ashx"}

     

    log local0. "[IP::client_addr]:[TCP::client_port]: updated URI to /Async/ServConnTest.ashx"

     

     

    Check if the URI contains the Forth URI

     

    } elseif {$uri contains "/leadseai/cmemailleadpub" }{

     

     

    Update the URI

     

    clientside {HTTP::uri "/Async/CMEmailLeadPub.ashx"}

     

    log local0. "[IP::client_addr]:[TCP::client_port]: updated URI to /Async/CMEmailLeadPub.ashx"

     

     

    Check if the URI contains the Fifth URI

     

    } elseif {$uri contains "/leadseai/salesleadpub" }{

     

     

    Update the URI

     

    clientside {HTTP::uri "/Async/SalesLeadPub.ashx"}

     

    log local0. "[IP::client_addr]:[TCP::client_port]: updated URI to /Async/SalesLeadPub.ashx"

     

     

    } else {

     

    Take some default action?

     

    log local0. "[IP::client_addr]:[TCP::client_port]: didn't match URI checks"

     

    }

     

    }

     

    }
  • nevermind,, figured it out...

     

     

     

    when HTTP_REQUEST_SEND {

     

     

    Save the URI to avoid running this command multiple times.

     

    set uri [string tolower [clientside {HTTP::uri}]]

     

    log local0. "[IP::client_addr]:[TCP::client_port]: \$uri: $uri"

     

     

    log local0. "[IP::client_addr]:[TCP::client_port]: selected server details: [LB::server]"

     

     

    Check if the selected server is .3 or .4

     

    if {[IP::addr [LB::server addr] equals 10.207.225.101] or [IP::addr [LB::server addr] equals 10.207.225.102] or [IP::addr [LB::server addr] equals 10.207.225.103]} {

     

     

    log local0. "[IP::client_addr]:[TCP::client_port]: matched server check for .3 or .4"

     

     

    Check if the URI contains the first string

     

    if {$uri contains "/gsfo/gsfopub"} {

     

     

    Update the URI

     

    clientside {HTTP::uri "/Async/CMReceive.ashx"}

     

    log local0. "[IP::client_addr]:[TCP::client_port]: updated URI to /Async/CMReceive.ashx"

     

     

    Check if the URI contains the second URI

     

    } elseif {$uri contains "/era/erapub" }{

     

     

    Update the URI

     

    clientside {HTTP::uri "/Async/ERAReceive.ashx"}

     

    log local0. "[IP::client_addr]:[TCP::client_port]: updated URI to /Async/ERAReceive.ashx"

     

     

    Check if the URI contains the third URI

     

    } elseif {$uri contains "/utilities/servconntest" }{

     

     

    Update the URI

     

    clientside {HTTP::uri "/Async/ServConnTest.ashx"}

     

    log local0. "[IP::client_addr]:[TCP::client_port]: updated URI to /Async/ServConnTest.ashx"

     

     

    Check if the URI contains the Forth URI

     

    } elseif {$uri contains "/leadseai/cmemailleadpub" }{

     

     

    Update the URI

     

    clientside {HTTP::uri "/Async/CMEmailLeadPub.ashx"}

     

    log local0. "[IP::client_addr]:[TCP::client_port]: updated URI to /Async/CMEmailLeadPub.ashx"

     

     

    Check if the URI contains the Fifth URI

     

    } elseif {$uri contains "/leadseai/salesleadpub" }{

     

     

    Update the URI

     

    clientside {HTTP::uri "/Async/SalesLeadPub.ashx"}

     

    log local0. "[IP::client_addr]:[TCP::client_port]: updated URI to /Async/SalesLeadPub.ashx"

     

     

    } else {

     

    Take some default action?

     

    log local0. "[IP::client_addr]:[TCP::client_port]: didn't match URI checks"

     

    }

     

    }

     

    }
  • hoolio's avatar
    hoolio
    Icon for Cirrostratus rankCirrostratus
    Nicely done. If you want to keep the spacing when you post a rule on DC, you can use the [ code ] [ /code ] tags (without the spaces).

     

     

     

    set uri [string tolower [clientside {HTTP::uri}]]

     

     

     

     

    Aaron

     

     

  • Colin_Walker_12's avatar
    Colin_Walker_12
    Historic F5 Account
    Very cool stuff! I featured a chunk of this as part of this week's 20 Lines or Less. Good work, and thanks for the contribution!

     

     

    Colin