Forum Discussion

Luca_55898's avatar
Luca_55898
Icon for Nimbostratus rankNimbostratus
Jun 27, 2011

Redirect to TCP port based on URL

Hello,

 

 

We have an Alteon load balancer that will be replaced with an LTM very soon.

 

 

We have a pool of two servers which run a bunch of different websites. The sites all use the same domain name, but just load different pages such as,

 

 

www.website.com/employees

 

www.website.com/customers

 

www.website.com/new_users

 

 

The servers run on an Apache host which knows what page to loaded based upon the TCP port people come in on. Currently the Alteon redirects incomming traffic to use either port 80,81 or 82 depending on which URL is entered into a browser.

 

 

So, can i create an iRule which will look at the incoming URL, then redirect traffic to the pool on either TCP 80,81, or 82?

 

I'm very new to iRules so if someone could point me in the right direction that would be good.

 

 

I know i could create a VIP for each site, but there are more than three and each requires HTTP and HTTPS so we would need a lot of VIPs. I'd also like to get my hands dirty with iRules.

 

 

So i know how to get started, just not how to redirect to a port.

 

 

when HTTP_REQUEST {

 

if {[HTTP::uri] equals {www.site1.com/test}} {HTTP::uri {www.site.com/test:81}

 

}

 

}

 

 

 

 

 

 

thoughts?

 

  • First, I noted that you were testing [HTTP::uri] for a match to "www.site1.com/test". Assuming that "www.site1.com" is the domain, that would never be true because [HTTP::uri] only contains the path and querystring parts of the URL. Take a look at the page below...It should help clarify the portions of a URL (i.e. HTTP::host, HTTP::uri, etc).

     

    http://devcentral.f5.com/Tutorials/TechTips/tabid/63/articleType/ArticleView/articleId/18/How-to-parse-a-URI.aspx

     

     

    I think you could do something like the following...

     

    when HTTP_REQUEST {

     

    switch -glob [HTTP::uri] {

     

    "/employees*" { pool pool-81 }

     

    "/customers*" { pool pool-82 }

     

    "/new_users*" { pool pool-83 }

     

    }

     

    }

     

    Obviously this assumes that you have created the pools (pool-81, pool-82, etc) that contain members listening on the appropriate port.
  • Peter's rule looks like a good start. You could use that rule on an HTTP and an HTTPS virtual server for whatever www.site1.com resolves to.

     

     

    Aaron
  • Thanks for the info.

     

     

    So in this case, I would not need to assign a pool to the VIP, correct?

     

    (Since you can only have one pool per VIP.)

     

     

    I would just use the iRule to rediect to the appropriate pool.... Am I on the right track here?

     

  • If you don't want to use a default pool on the virtual server, you'd want to ensure that you assign a pool in each case in the switch statement:

    
    when HTTP_REQUEST {
       switch -glob [HTTP::uri] {
          "/employees*" { pool pool-81 }
          "/customers*" { pool pool-82 }
          "/new_users*" { pool pool-83 }
          default { pool pool-80 }
       }
    }
    

    Aaron
  • You may want to explore using datagroups (classes) so that you don't have to edit the irule every time you want to add or remove a URI/pool combo.

     

     

    If you are only concerned with a top level directory, here is some code that may help you out:

     

     

    rule topdir_to_pool {

     

    when HTTP_REQUEST {

     

    extracting the top level directory name

     

    set HTTPtopdir [lindex [split [string tolower [HTTP::uri]] /] 1]

     

    seeing if the top level directory name in our the server_pool class

     

    if {[class match $HTTPtopdir equals server_pool]} {

     

    extracting the pool associated with the top level directory

     

    set HTTPtopdir_pool [class lookup $HTTPtopdir server_pool]

     

    log local0. "request for $HTTPtopdir, using pool $HTTPtopdir_pool"

     

    using the pool found associated to the top level directory

     

    pool $HTTPtopdir_pool

     

    }

     

    implicit else, where we fall back to the default pool defined in the virtual server config

     

    }

     

    }

     

     

    class server_pool {

     

    {

     

    "customers" { "pool-82" }

     

    "employees" { "pool-81" }

     

    "new_users" { "pool-83" }

     

    }

     

    }
  • Nice idea, Ryan. You could also use URI::path to save a bit on parsing the first directory:

     

     

    [URI::path [HTTP::uri] 1 2]

     

     

    http://devcentral.f5.com/wiki/default.aspx/iRules/uri__path

     

     

    Aaron
  • Thanks for the help guys. I have it working using the iRule hoolio provided.

     

    The datagroups one looks at bit out of my league at the moment :-)
  • If you want to drop the requests which don't match, it's much cleaner to use the default case to call the drop command. You could leave it out but then I think you'd need a OneConnect profile.

     

     

    http://devcentral.f5.com/wiki/default.aspx/iRules/drop

     

     

    Aaron