Forum Discussion

Termark's avatar
Aug 14, 2024

Load Balance 4 URI over 2 IPs and rewrite http response location

I have been struggling with this and I hope someone can assist.

The challenge is twofold:
1. Need Virtual Server to load balance between 4 URIs which are spread over 2 Nodes.

2. When the webservers respond, they respond with a location which points to itself instead of the FQDN the client specified

 

I have tried solving with numerous variations of below iRules, but fail when the client receives the Nodes http://hostname:portnumber/URi/web2.exe (which isn't reachable from client network).

@1: Irule to load balance between 4 URIs:

Virtual Server name: vs_example.com

IP: 172.16.0.1

b. Pools:

pool_example1-uri-1_81

- node_01_10.0.0.1:81

pool_example1-uri-2_81

- node_01_10.0.0.1:81

pool_example2-uri-3_81

- node_02_10.0.0.2:81

pool_example2-uri-4_81

- node_02_10.0.0.2:81

c. iRule:

when HTTP_REQUEST {
    # Check if the requested URI is either / or /CAisd/pdmweb.exe
    if { [HTTP::uri] eq "/" or [HTTP::uri] eq "/CAisd/pdmweb.exe" } {
        # Define the possible URIs and corresponding pools
        set uri_pool_map {
            /URi/web1.exe pool_example1-uri-1_80
            /URi/web2.exe pool_example1-uri-2_80
            /URi/web3.exe pool_example1-uri-3_80
            /URi/web4.exe pool_example1-uri-4_80
        }

        # Initialize a list of available pools
        set available_uri_pool_list {}

        # Check the availability of each pool and add to the list if available
        for {set i 0} {$i < [llength $uri_pool_map]} {incr i 2} {
            set pool_name [lindex $uri_pool_map [expr {$i + 1}]]
            if {[active_members $pool_name] > 0} {
                lappend available_uri_pool_list [lindex $uri_pool_map $i] $pool_name
            } else {
                log local0. "Pool $pool_name is not available"
            }
        }

        # If no pools are available, send an error response
        if {[llength $available_uri_pool_list] == 0} {
            HTTP::respond 503 content "Service Unavailable - No available pools"
            return
        }

        # Select the next URI and corresponding pool in a round-robin fashion from available pools
        set index [expr {[clock clicks -milliseconds] % ([llength $available_uri_pool_list] / 2)}]
        set next_uri [lindex $available_uri_pool_list [expr {$index * 2}]]
        set next_pool [lindex $available_uri_pool_list [expr {$index * 2 + 1}]]

        # Log the selected URI and pool for troubleshooting
        log local0. "Selected URI: $next_uri, Pool: $next_pool"

        # Replace the URI with the selected one
        HTTP::uri $next_uri

        # Select the corresponding pool
        pool $next_pool
    }
}

 

 

@2. iRule to replace location in HTTP Response 

when HTTP_RESPONSE_RELEASE {
    if { [HTTP::header exists "Location"] } {
        set location [HTTP::header "Location"]
        log local0. "Original Location header: $location"

        # Modify the Location header if it contains the internal server reference
        if { $location starts_with "http://webserver1" || $location starts_with "http://webserver2" } {
            set new_location [string map {
                "http://webserver1:81" "https://172.16.0.1"
                "https://webserver1:81" "https://172.16.0.1"
                "http://webserver2:81" "https://172.16.0.1"
                "https://webserver2:81" "https://172.16.0.1"
            } $location]
            HTTP::header replace "Location" $new_location
            log local0. "Modified Location header: $new_location"
        }
    }
}



  • You are better off changing the configuration on the server that is sending the redirect. The web server should send back the correct host rather than its own IP. You might be able to correct this on the F5 but it would be much more complicated.