Forum Discussion

Kaloyan's avatar
Kaloyan
Icon for Cirrus rankCirrus
Oct 19, 2017

iRule pointing traffic from one pool member to another with HTTP::retry

Hi, I have the following traffic path: Client request -> External VIP ->pool with member with IP:port of internal VIP -> Internal VIP -> Pool with one member, which respond always with 307 redirect to an application server.

 

The idea is to break the 307 response on the LB Internal VIP and make HTTP::retry with the original request to the redirected Location.I was able to accomplish this by the iRule below.The customer responds that the iRule is working fine when a browser is used. With this type of connections, I am using cookies.When they use application for the requests (which are only POST requests), they see only a half of them on the backend server. The request-app don't support cookies, so I made X-Forwarded-For persistence, and I see the records in the persistence table for the right source IPs.All profiles are a default. Only X-Forwarded-For insertion on the external VIP.

 

Error on the backend server:iRule to follow...

 

3 Replies

  • Here is the iRule:
    
        when CLIENT_ACCEPTED {
                set server 0
                set retried 0
                set default_pool [LB::server pool]
        }
        when HTTP_REQUEST {
            set clientip ""
            if { [HTTP::header exists "X-Forwarded-For"] } {
                set clientip [lindex [ split [lindex [HTTP::header values X-Forwarded-For] 0] "," ] 0]
            } else {
                set clientip [IP::client_addr]
            }
            log local0. "persist lookup on REQUEST: $clientip"      
              if { [HTTP::cookie exists test1] } {
                        pool test_1
                        persist cookie insert test1 0
                        log local0. "FROM_ifcheck_cookie_exist_HDLtest1 HTTP request: [HTTP::request]"
                }
                elseif { [HTTP::cookie exists test2] } {
                        pool test_2
                        persist cookie insert test2 0
                        log local0. "FROM_ifcheck_cookie_exist_HDLtest2 HTTP request: [HTTP::request]"
                }
                elseif { ($retried == 0) } {
                        set request_headers [HTTP::request]
                         Set payload content legth to capture. 
                        if {[HTTP::header exists "Content-Length"] && [HTTP::header "Content-Length"] <= 4000000}{ 
                            set content_length [HTTP::header "Content-Length"] 
                        } 
                        else { 
                            set content_length 4000000 
                        } 
                            Capture HTTP payload from request, HTTP::collect triggers event HTTP_REQUEST_DATA 
                        if { [info exists content_length] && $content_length > 0} { 
                            HTTP::collect $content_length 
                        }
                        pool $default_pool
                        persist none
                }
                elseif { ($retried == 1) } {
                Check DGL external-ip-check for IP/X-Forwarded-For match and assign uie persistence
                if {[class match $clientip equals "external-ip-check"]} {
                        switch -glob $server {
                                "1" {
                                     pool test_1
                                     persist uie $clientip 1800
                                     log local0. "FROM_retried_check_SP_test1 HTTP request: [HTTP::request]"
                                }
                                "2" {
                                     pool test_2
                                     persist uie $clientip 1800
                                     log local0. "FROM_retried_check_SP_test2 HTTP request: [HTTP::request]"
                                    }
                                default {
                                        log local0. "Configuration needed for HTTP_REQUEST. HTTP request: [HTTP::request]"
                                }
                        }
                } else {
                        switch -glob $server {
                                "1" {
                                     pool test_1
                                     persist cookie insert test1 0
                                     log local0. "FROM_retried_check_with_cookie_test1 HTTP request: [HTTP::request]"
                                }
                                "2" {
                                     pool test_2
                                     persist cookie insert test2 0
                                     log local0. "FROM_retried_check_with_cookie_test2 HTTP request: [HTTP::request]"
                                    }
                                default {
                                        log local0. "Configuration needed for HTTP_REQUEST. HTTP request: [HTTP::request]"
                                }
                        }
                }
        }
        }
        when HTTP_REQUEST_DATA { 
                                 Set payload, depends on HTTP::collect done in HTTP_REQUEST event. 
                                set payload [HTTP::payload] 
    
                                 Append HTTP payload to HTTP request header to form a complete HTTP post request (request + payload) 
                                append request_headers [HTTP::payload [HTTP::payload length]] 
        } 
        when HTTP_RESPONSE {
                if { ([HTTP::status] == 307) } {
                        log local0. "HTTP_RESPONSE from Dispatcher: [HTTP::header Location] for HTTP request: $request_headers"
                        set retried 1
                                    switch -glob [string tolower [HTTP::header Location]] {
                                    "*:first/*" 
                                    {
                                        set server 1
                                        HTTP::retry "$request_headers"
                                    }
                                    "*:second/*"
                                    {
                                        set server 2
                                        HTTP::retry "$request_headers"
                                    }
                                    default {
                                        set server 0
                                        log local0. "Configuration needed for HTTP_RESPONSE. New location from Dispatcher: [HTTP::header Location] for HTTP request: $request_headers"
                                }
        }
                }
                else {
                        log local0. "HTTP_RESPONSE from APP-server: [HTTP::response]"
                }
        }
    
  • In general I think you should add a persistency record in the HTTP_RESPONSE event via the:

    persist add uie  
    command

    In the HTTP_REQUEST you can persist to the server by using the:

    persist uie  
    command

  • Thanks, jurgenvdmark. I was aware of this possibility for "persist add uie" in the HTTP_RESPONSE. Will add it as well... Right now, I am trying to completely modify the iRule, using sideband collection options, as HTTP::retry seems to have problems with these POST requests...