Forum Discussion

Sylvain_85827's avatar
Jul 02, 2013

Rewrite URL based on selected node for load-balancing

Dears iRules Gurus and community,

 

Once again I need your help ^^ I'm wondering how to rewrite an URL of HTTP requests (IPP in fact) depending on the node chosen for load-balancing the traffic.

 

Typically in ASCII ART or RFC style this would give:

 

|| ----- if node1 selected for load-balancing -----> https://mynode1/xxxxxx ----> node 1 IIS server

 

https://mypublicurl/xxxxxx ----> || f5 LTM v11 || ----- if node2 selected for load-balancing -----> https://mynode2/xxxxxx ----> node 2 IIS server

 

|| ----- if node3 selected for load-balancing -----> https://mynode3/xxxxxx ----> node 3 IIS server

 

|| etc...

 

Any idea?

 

Thanks for your very valuable (and appreciated :D) help!

 

Cheers.

 

18 Replies

  • I was going under the assumption that you wouldn't know the host value in the redirect, but yes this other method would work if you did know it.
  • Hi,

     

     

    it's me again 🙂 but this time only for giving you feedback.

     

     

    @Kevin

     

     

    I don't know why below code caught all the host name between https:// and the next / except the first letter!

     

     

     if { [scan $uri_old {%*[http://|https://]%[^/]} host_old] } { 

     

     

    So I changed it like this:

     

     if { [scan $uri_old {%[^//]//%[^/]]} host_tmp host_old] } { 

     

    Certainly not the best, but at least it is working 😄

     

     

    Finally the iRule became:

     

    
    when RULE_INIT {
    
         Log debug messages to /var/log/ltm? 1=yes, 0=no
        set static::rewrite_debug 1
        
         External hostname for the web application
        set static::external "mypublicsite.com"
    }
    
    when HTTP_REQUEST_SEND {
    
         Need to force the host header replacement and HTTP:: commands into the clientside context
         as the HTTP_REQUEST_SEND event is in the serverside context
        clientside {
    
             Different action depending on the node selected for load-balancing
            switch [LB::server addr] {
    
                "1.1.1.1" {
    
                    HTTP::header replace Host "internalhost01.com"
                    if {$static::rewrite_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: HTTP Host header rewritten with internalhost01.com"}
                }
                "1.1.1.2" {
           
                    HTTP::header replace Host "internalhost02.com"
                    if {$static::rewrite_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: HTTP Host header rewritten with internalhost02.com"}
                }
            }
        }
    }
    
    when HTTP_RESPONSE {
    
         Replace all internal Host headers with $static::external value defined in RULE_INIT section
        HTTP::header replace Host $static::external
        if {$static::rewrite_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: HTTP Host header rewritten with -> $static::external"}
    
        if { [HTTP::is_redirect] } {
    
             Log if we detect an HTTP redirection
            if {$static::rewrite_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: HTTP redirection detected"}
    
             Store Location HTTP header coming from backend server
            set uri_old [string tolower [HTTP::header Location]]
            
             Store backend server host name
            if { [scan $uri_old {%[^//]//%[^/]]} host_tmp host_old] } {
    
                 Replace backend server host name with external host name into HTTP Location header
                set map_exp "set uri_new \[string map {$host_old $static::external} $uri_old\]"
                eval $map_exp
                
                 Finally rewrite HTTP Location header
                HTTP::header replace Location $uri_new
                if {$static::rewrite_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: HTTP Location header rewritten with -> $uri_new"}
            }
        }
    }
     

     

     

    I sincerely thank you all for your very valuable help! Without you this story would have taken me too much time, really thank you.

     

  • Posted By nitass on 07/10/2013 06:35 AM

     

    ...

     

     

    Can't read your reply sorry...

     

     

     

  • Got it in my email but I'm really not sure about what you replied exactly, can you please explain nitass?

     

     

  • I don't know why below code caught all the host name between https:// and the next / except the first letter!i understand square brackets treat thing inside as character rather than word. for example, [https] means h, t, p and s characters. so, if hostname starts with one of them, it will be included.

     

     

    tcl scan

     

    [chars]

     

    The input substring consists of one or more characters in chars. The matching string is stored in the variable. If the first character between the brackets is a ] then it is treated as part of chars rather than the closing bracket for the set. If chars contains a sequence of the form a-b then any character between a and b (inclusive) will match. If the first or last character between the brackets is a -, then it is treated as part of chars rather than indicating a range.

     

     

    % set uri_old "http://some.domain.com/something"
    http://some.domain.com/something
    
    % scan $uri_old {%*[http://|https://]%[^/]} host_old
    1
    
    % put $host_old
    ome.domain.com
    
  • Thank you all for your help! I learn so much with you and have a lot of fun by the way ^^