Learn F5 Technologies, Get Answers & Share Community Solutions Join DevCentral

Filter by:
  • Solution
  • Technology
Answers

iRule to persist node selection across redirect...

Afternoon all,

It's been a while since I've posted on here :)

Anyhow, I'm currently working on a new functionality piece for our F5 setup, whereby the F5 needs to host a 'landing page', and then select a back-end node based on whatever button was clicked...
Serving the HTML and Images is a nice n easy, as got boiler plate code already for that... I've also had a working node selection based on button click...

However, where I've hit a stumbling block is getting that node selection to persist across a redirect...

The URI struct I've got provides looks like '/redirect/', with selector being 'adult' or 'child' in this case, however could be anything...
The string to node selection is stored in a datagroup, which the iRule queries to get a matching node value...

ltm data-group internal landingpage_vm2_redirects {
    records {
        adult {
            data 192.168.18.26:9080
        }
        child {
            data 192.168.18.26:10080
        }
    }
    type string
}
 

iRule looks like:
*CAVEAT* There's a lot of vars etc in here that aren't set within this rule... That's due to a wider iRule framework being used on our F5's :)
when RULE_INIT  {

    # LandingPage Debug variable.
    set static::LandingPageDebug 1

}

when HTTP_REQUEST priority 450 {
    if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Processing HTTP_REQUEST at priority 450." }
    
    # Check if there is a landing page for this VIP
    if { [class match $vname equals LandingPage_VIPS ] } {
        if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Got a VIP with a Landing Page." }
        
        # Set the standard LandingPage Prefix
        set landingpage_prefix "landingpage_"
        
        # Make sure response_sent = 0
        set response_sent 0
        
        # Pull out the suffix for this Landing Page
        set lp_scheme_id [class lookup $vname LandingPage_VIPS]
        if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Landing Page scheme ID = $lp_scheme_id." }
        
        # Are we on root?
        if { [string tolower [HTTP::path]] equals "/" } {
            if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Root HTTP::Path, checking for HTML file..." }
            # Need to return the HTML file
            set lp_html_ifile $landingpage_prefix
            append lp_html_ifile $lp_scheme_id
            append lp_html_ifile "_html"
            
            # Load the iFile contents into a var, catch any errors.
            catch {ifile get $lp_html_ifile} lp_html
            
            # Check if we got a valid iFile.
            if { $lp_html == "" } {
                if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: \$lp_html is empty. Skipping..." }
                return
            } else {
                if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Got a valid \$lp_html variable." }
                # Flag that a landing page has been sent, and disable any existing persistence...
                set landingpage_sent 1
                persist none
                set cookie "JSESSIONID=; version=1; path=/; Expires=Thu, 01-Jan-1970 00:00:00 GMT; HttpOnly"
                HTTP::respond 200 content $lp_html noserver "Content-Type" "text/html" "Set-Cookie" $cookie
                return
            }
        # Next is images...
        } elseif { [string tolower [HTTP::path]] starts_with "/images" and [string tolower [HTTP::path]] ends_with ".png" } {
            if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Got an image path." }
            
            # Save the image_name for later use
            set image_name [string range [HTTP::uri] [expr [string last "/" [HTTP::uri]] + 1] end]
            if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Looking for image $image_name." }
            
            # Construct DG name
            set lp_images_dg $landingpage_prefix
            append lp_images_dg $lp_scheme_id
            append lp_images_dg "_images"
            if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Images datagroup = $lp_images_dg." }
        
            ## Check if the image actually exists in datagroup
            if { [class match $image_name equals $lp_images_dg] } {
                if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Got a valid image, returning..." }
                HTTP::respond 200 content [b64decode [class lookup $image_name $lp_images_dg]] noserver \
                    "Content-Type" "image/png" \
                    "Last-Modified" "Sun, 29 Mar 1970 18:53:56 GMT"
                set landingpage_sent 1
                persist none
                return
            } else {
                if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Got an invalid image name." }
                HTTP::respond 200 content [b64decode [class lookup 'transparent.png' landingpage_images]] noserver \
                    "Content-Type" "image/png" \
                    "Last-Modified" "Sun, 29 Mar 1970 18:53:56 GMT"
                set landingpage_sent 1
                persist none
                return
            }
        } elseif { [string tolower [HTTP::path]] starts_with "/redirect" } {
            if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Got a redirect path, looking for redirect value..." }
            
            set redirect_name [string range [HTTP::uri] [expr [string last "/" [HTTP::uri]] + 1] end]
            if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Looking for redirect for $redirect_name." }
            
            # Construct DG name
            set lp_redirects_dg $landingpage_prefix
            append lp_redirects_dg $lp_scheme_id
            append lp_redirects_dg "_redirects"
            if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Redirects datagroup = $lp_redirects_dg." }
            
            # Check if the redirect value exists in the DG
            if { [class match $redirect_name equals $lp_redirects_dg] } {
                
                # Pull out the node from DG
                set node [class lookup $redirect_name $lp_redirects_dg]
                if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Redirect node = $node." }
                
                # Get a list of active members for this VS pool
                set VSPool [LB::server pool]
                set live_members [active_members -list $VSPool]
                if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Pool = $VSPool, Live_members = $live_members." }
                
                # Split the node into ip and port
                set node_ip [lindex [split $node ":"] 0]
                set node_port [lindex [split $node ":"] 1]
                
                # check if the desired node is active, then send the
                # request to it, otherwise send to pool to an alternate server
                if {$live_members contains [list $node_ip $node_port]} {
                    if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Sending request to $node_ip $node_port." }
                    node $node_ip $node_port
                    # Unset the landingpage_set var
                    set landingpage_sent 0
                    
                    # Redirect to default
                    # Check for VIP specific over-rides first.
                    set rurl [class match -value $cuname equals ProxyPass_Default]
                    if {$rurl eq ""} {
                        # Fallback to standard redirect.
                        set rurl [class match -value $cname equals ProxyPass_Default]
                    }
                    if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Redirecting request to $rurl." }
                    # Flag the response
                    set response_sent 1
                    # Disable any existing persistence
                    persist source_addr
                    if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Temp persistenance record added." }
                    # Perform the default redirect.
                    HTTP::respond 302 noserver Location "$protocol[HTTP::host]$rurl"
                } else {
                    if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: $node_ip $node_port not in live_members list..." }
                    set ppass_error 1
                }
                
            }
        }
    }
}

 

An example connection log looks like http://pastebin.com/rtHmaxT4
Line 38 sets the node selection.
Line 39 triggers the client side redirection.

Any pointers greatly appreciated... 

Regards
Gavin

0
Rate this Question

Answers to this Question

placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
It's probably worth adding that once past the landing page, the application supports JSESSIONID cookies... So persistence should then be handled easily...

Gav
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
An example connection log looks like http://pastebin.com/rtHmaxT4
Line 38 sets the node selection.
Line 39 triggers the client side redirection.
just wondering why you need both "node" and "HTTP::respond 302" commands at the same time.
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
Posted By nitass on 08/07/2013 09:32 PM
An example connection log looks like http://pastebin.com/rtHmaxT4
Line 38 sets the node selection.
Line 39 triggers the client side redirection.
just wondering why you need both "node" and "HTTP::respond 302" commands at the same time.


Nitass, the respond is there to get the user from the redirect page to correct application default page (home.faces)... Which I suspect is what's causing the issue with node selection :-( Gav
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
the respond is there to get the user from the redirect page to correct application default page (home.faces)...
you are saying application default page (e.g. /home.faces) depends on selected node, aren't you? for example, in pastebin.com line 38, 192.168.18.26:9080 is chosen and /home/faces is its application default page. if 192.168.18.26:10080 is selected instead, is application default page still /home/faces?
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
Posted By nitass on 08/08/2013 12:09 AM
the respond is there to get the user from the redirect page to correct application default page (home.faces)...
you are saying application default page (e.g. /home.faces) depends on selected node, aren't you? for example, in pastebin.com line 38, 192.168.18.26:9080 is chosen and /home/faces is its application default page. if 192.168.18.26:10080 is selected instead, is application default page still /home/faces?

Nitass, yes, the default application page could depend on the node being selected... However in this case, both nodes use /home.faces...

Cheers
Gavin
 

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
However in this case, both nodes use /home.faces...
so, why do you need to persist node before redirection (i.e. at line 38)? can we persist when redirection request (GET /home.faces) is coming?
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
Posted By nitass on 08/08/2013 01:04 AM
However in this case, both nodes use /home.faces...
so, why do you need to persist node before redirection (i.e. at line 38)? can we persist when redirection request (GET /home.faces) is coming?

The 2 back-end nodes are hosting 2 slightly different versions of the same application... One customised for 'Adult', and one for 'Child'...

Hence the need for a DG lookup to determine the correct node based on the application variant being requested...

Guess an alternative might be to put a query string on the URL being requested... That way could hit the actual application to use JSESSIONID persistence, and then redirect to remove the query string...

 

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
The 2 back-end nodes are hosting 2 slightly different versions of the same application... One customised for 'Adult', and one for 'Child'...
Hence the need for a DG lookup to determine the correct node based on the application variant being requested...
when responding 302, may we manually add cookie? so, when redirection request (e.g. GET /home/faces) is coming along with the cookie, we can check and send it to correct node.
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
Posted By nitass on 08/08/2013 01:24 AM
The 2 back-end nodes are hosting 2 slightly different versions of the same application... One customised for 'Adult', and one for 'Child'...
Hence the need for a DG lookup to determine the correct node based on the application variant being requested...
when responding 302, may we manually add cookie? so, when redirection request (e.g. GET /home/faces) is coming along with the cookie, we can check and send it to correct node.

Yep, could look at adding a cookie into the 302 redirect... Is there an easy method of generating a pseudo JSESSIONID that could work with the existing persistance functionality?

 

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
Yep, could look at adding a cookie into the 302 redirect...
what about something like this?

e.g.
[root@ve10:Active] config # b virtual bar list
virtual bar {
   snat automap
   destination 172.28.19.252:80
   ip protocol 6
   rules myrule
   profiles {
      http {}
      tcp {}
   }
}
[root@ve10:Active] config # b rule myrule list
rule myrule {
   when HTTP_REQUEST {
  set uri [HTTP::uri]
  switch $uri {
    "/redirect/adult" { set ckvalue 1 }
    "/redirect/child" { set ckvalue 2   }
    default {
      set ck [HTTP::cookie value ckname]
      switch $ck {
        1 { node 200.200.200.101 80; return }
        2 { node 200.200.200.111 80; return }
        default {
          # do something
        }
      }
    }
  }
  HTTP::respond 302 noserver Location "http://[HTTP::host]/something" "Set-Cookie" "ckname=$ckvalue;path=/"
}
}

# /redirect/adult

[root@ve10:Active] config # ssldump -Aed -nni 0.0 port 80
New TCP connection #1: 192.168.206.136(56779) <-> 172.28.19.252(80)
1375951170.1617 (0.0029)  C>S
---------------------------------------------------------------
GET /redirect/adult HTTP/1.1
Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: en-US
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3; MS-RTC LM 8; .NET4.0E)
Accept-Encoding: gzip, deflate
Host: 172.28.19.252
Connection: Keep-Alive

---------------------------------------------------------------

1375951170.1618 (0.0000)  S>C
---------------------------------------------------------------
HTTP/1.0 302 Found
Location: http://172.28.19.252/something
Set-Cookie: ckname=1;path=/
Connection: Keep-Alive
Content-Length: 0

---------------------------------------------------------------

1375951170.1669 (0.0050)  C>S
---------------------------------------------------------------
GET /something HTTP/1.1
Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: en-US
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3; MS-RTC LM 8; .NET4.0E)
Accept-Encoding: gzip, deflate
Host: 172.28.19.252
Connection: Keep-Alive
Cookie: ckname=1

---------------------------------------------------------------

New TCP connection #2: 200.200.200.10(56779) <-> 200.200.200.101(80)
1375951170.1678 (0.0008)  C>S
---------------------------------------------------------------
GET /something HTTP/1.1
Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: en-US
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3; MS-RTC LM 8; .NET4.0E)
Accept-Encoding: gzip, deflate
Host: 172.28.19.252
Connection: Keep-Alive
Cookie: ckname=1

---------------------------------------------------------------

# /redirect/child

[root@ve10:Active] config # ssldump -Aed -nni 0.0 port 80
New TCP connection #1: 192.168.206.136(56780) <-> 172.28.19.252(80)
1375951232.4539 (0.0039)  C>S
---------------------------------------------------------------
GET /redirect/child HTTP/1.1
Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: en-US
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3; MS-RTC LM 8; .NET4.0E)
Accept-Encoding: gzip, deflate
Host: 172.28.19.252
Connection: Keep-Alive

---------------------------------------------------------------

1375951232.4540 (0.0000)  S>C
---------------------------------------------------------------
HTTP/1.0 302 Found
Location: http://172.28.19.252/something
Set-Cookie: ckname=2;path=/
Connection: Keep-Alive
Content-Length: 0

---------------------------------------------------------------

1375951232.4579 (0.0038)  C>S
---------------------------------------------------------------
GET /something HTTP/1.1
Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: en-US
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3; MS-RTC LM 8; .NET4.0E)
Accept-Encoding: gzip, deflate
Host: 172.28.19.252
Connection: Keep-Alive
Cookie: ckname=2

---------------------------------------------------------------

New TCP connection #2: 200.200.200.10(56780) <-> 200.200.200.111(80)
1375951232.4599 (0.0019)  C>S
---------------------------------------------------------------
GET /something HTTP/1.1
Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: en-US
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3; MS-RTC LM 8; .NET4.0E)
Accept-Encoding: gzip, deflate
Host: 172.28.19.252
Connection: Keep-Alive
Cookie: ckname=2

---------------------------------------------------------------


Is there an easy method of generating a pseudo JSESSIONID that could work with the existing persistance functionality?
i understand persistence record is created after pool member is selected but in this case, you want to make decision before request is sent to pool member.
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

Nitass, cheers for the pointers...

Looks like I've finally got a working iRule :)
Followed your tip of setting a cookie value on redirect, and then looking for that cookie on the subsequent GET request...
Had to add an additional flag to trigger a remove of the cookie after the first GET, else it was doing something funny...

Final iRule looks like:

when RULE_INIT {

# LandingPage Debug variable.
set static::LandingPageDebug 1

# Set the standard LandingPage Prefix
set static::landingpage_prefix "landingpage_"
}

when HTTP_REQUEST priority 450 {
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Processing HTTP_REQUEST at priority 450." }

# Check if there is a landing page for this VIP
if { [class match $vname equals LandingPage_VIPS ] } {
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Got a VIP with a Landing Page." }

# Make sure response_sent = 0
set response_sent 0

# Pull out the suffix for this Landing Page
set lp_scheme_id [class lookup $vname LandingPage_VIPS]
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Landing Page scheme ID = $lp_scheme_id." }

# Are we on root?
if { [string tolower [HTTP::path]] equals "/" } {
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Root HTTP::Path, checking for HTML file..." }
# Need to return the HTML file
set lp_html_ifile $static::landingpage_prefix
append lp_html_ifile $lp_scheme_id
append lp_html_ifile "_html"

# Load the iFile contents into a var, catch any errors.
catch {ifile get $lp_html_ifile} lp_html

# Check if we got a valid iFile.
if { $lp_html == "" } {
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: \$lp_html is empty. Skipping..." }
return
} else {
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Got a valid \$lp_html variable." }
# Flag that a landing page has been sent, and disable any existing persistence...
set landingpage_sent 1
persist none
set cookie "JSESSIONID=; version=1; path=/; Expires=Thu, 01-Jan-1970 00:00:00 GMT; HttpOnly"
HTTP::respond 200 content $lp_html noserver "Content-Type" "text/html" "Set-Cookie" $cookie
return
}

# Next is images...
} elseif { [string tolower [HTTP::path]] starts_with "/images" and [string tolower [HTTP::path]] ends_with ".png" } {
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Got an image path." }

# Save the image_name for later use
set image_name [string range [HTTP::uri] [expr [string last "/" [HTTP::uri]] + 1] end]
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Looking for image $image_name." }

# Construct DG name
set lp_images_dg $static::landingpage_prefix
append lp_images_dg $lp_scheme_id
append lp_images_dg "_images"
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Images datagroup = $lp_images_dg." }

## Check if the image actually exists in datagroup
if { [class match $image_name equals $lp_images_dg] } {
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Got a valid image, returning..." }
HTTP::respond 200 content [b64decode [class lookup $image_name $lp_images_dg]] noserver \
"Content-Type" "image/png" \
"Last-Modified" "Sun, 29 Mar 1970 18:53:56 GMT"
set landingpage_sent 1
persist none
return
} else {
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Got an invalid image name." }
HTTP::respond 200 content [b64decode [class lookup 'transparent.png' landingpage_images]] noserver \
"Content-Type" "image/png" \
"Last-Modified" "Sun, 29 Mar 1970 18:53:56 GMT"
set landingpage_sent 1
persist none
return
}

} elseif { [string tolower [HTTP::path]] starts_with "/redirect" } {
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Got a redirect path, looking for redirect value..." }

set redirect_name [string range [HTTP::uri] [expr [string last "/" [HTTP::uri]] + 1] end]
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Looking for redirect for $redirect_name." }

# Add a cookie to the redirect
set selection_cookie "selection=$redirect_name; version=1; path=/; HttpOnly"
# Redirect to default
# Check for VIP specific over-rides first.
set rurl [class match -value $cuname equals ProxyPass_Default]
if {$rurl eq ""} {
# Fallback to standard redirect.
set rurl [class match -value $cname equals ProxyPass_Default]
}
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Redirecting request to $rurl." }
# Flag the response
set response_sent 1
# Disable any existing persistence
persist none
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Persistence disabled..." }

# Cookie sent flag?
set selection_cookie_sent 1

# Perform the default redirect.
HTTP::respond 302 noserver Location "$protocol[HTTP::host]$rurl" "Set-Cookie" $selection_cookie
} else {

if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Got an application path, processing..." }

# Construct DG name
set lp_redirects_dg $static::landingpage_prefix
append lp_redirects_dg $lp_scheme_id
append lp_redirects_dg "_redirects"
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Redirects datagroup = $lp_redirects_dg." }

# Pull the cookie value
set selection [HTTP::cookie value selection]

# Check if the cookie value is set
if { $selection ne "" } {
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Got a selection cookie value of $selection." }
# Check if the redirect value exists in the DG
if { [class match $selection equals $lp_redirects_dg] } {

# Pull out the node from DG
set node [class lookup $selection $lp_redirects_dg]
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Redirect node = $node." }

# Get a list of active members for this VS pool
set VSPool [LB::server pool]
set live_members [active_members -list $VSPool]
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Pool = $VSPool, Live_members = $live_members." }

# Split the node into ip and port
set node_ip [lindex [split $node ":"] 0]
set node_port [lindex [split $node ":"] 1]

# check if the desired node is active, then send the
# request to it, otherwise send to pool to an alternate server
if {$live_members contains [list $node_ip $node_port]} {
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Sending request to $node_ip $node_port." }
pool $VSPool member $node_ip $node_port
#node $node_ip $node_port
# Unset the landingpage_set var
set landingpage_sent 0

return

} else {
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: $node_ip $node_port not in live_members list..." }
set ppass_error 1
}

}
} else {
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Invalid Selection cookie value..." }
if { [HTTP::cookie "JSESSIONID"] ne "" } {
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Valid JSESSIONID cookie present." }
return
} else {
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: No JSESSIONID cookie present, redirecting to /..." }
HTTP::respond 302 noserver Location "$protocol[HTTP::host]"
}
}
}
}
}

when HTTP_RESPONSE priority 450 {
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Processing HTTP_RESPONSE at priority 450." }

# Check if we've previously sent a selection cookie.
if { [info exists selection_cookie_sent] && $selection_cookie_sent == 1 } {
if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Selection cookie previously sent. Removing..."}
HTTP::cookie insert name "selection" value "set" version 1
HTTP::cookie maxage "selection" 0
# Unset the flag
unset selection_cookie_sent
}

if { $static::LandingPageDebug or $f5_connection_debug } { log local0.debug "$log_prefix: Finished response."}

}



Cheers again.

Gav

0