HTTP redirect to HTTPS with pool down detection
Problem this snippet solves:
I pieced this together from several rules because I couldn't find a rule that would do everything I wanted. The other rules were also specifically naming a pool, which means I had to have one irule for every VIP/pool. This one is generic so it can be used with many VIPs.
This rule is basically a decision tree. If a pool has at least one available member it keeps sending requests to the pool. If a pool has no available members, it will redirect to a /maintenance URI, which the content is then served from the irule itself. The maintenance URI just says the site is unavailable, and keeps refreshing every 60 seconds so that when the pool comes up again the users are automatically redirected back to the site via javascript. The redirect to the maintenance URI is also done via javascript. Javascript is used for two reasons: first, some versions of IE have redirections disabled as a security measure; second, if any of your sites use frames like one of ours does, Javascript will break the user out of the frames. That way the frames don't stick around while the active frame shows the maintenance window.
UPDATE 8-5-2009
I added a persistence override feature so you can force your connections to a specific pool member for http/https for testing through the VIP, cleaned up several bugs, and added on/off switches at the top. Go to this URI to set the persistence override:
/F5NODEPERSIST&< IP Address of node>
The override will stay until the browser is closed or the cookie is cleared.
Code :
when HTTP_REQUEST { ##################################################### #set some variables: # sets the timer to return client to host URL set sectime 60 #if we want to redirect any uri's consisting of / to anywhere, set the following entries: #0=off, 1=on set redirectdefaulturlon 0 #and set the URI that you want to redirect to: set redirectdefaulturl "" #Turn on redirect of http to https? #0=off, 1=on set redirectsecureon 0 #enable persistence override? #0=off, 1=on set persistenceoverrideon 0 ##################################################### #set the incoming port, so we know what port to use on the server side if {[TCP::local_port] == 443} { set incomingport 80 } else { set incomingport [TCP::local_port] } if { $persistenceoverrideon == 1 } { #check for a cookie override on persistence if { [HTTP::cookie exists "F5NODEPERSIST"]} { node [HTTP::cookie F5NODEPERSIST] $incomingport log "[IP::client_addr]:[TCP::client_port]: New request to [IP::local_addr]:[TCP::local_port] for [HTTP::uri], sent to node [HTTP::cookie F5NODEPERSIST]:$incomingport" set activememberslbpool 1 } else { set activememberslbpool [active_members [LB::server pool] ] } #check if we need to set persistence override if {[HTTP::uri] contains "/F5SERVERSELECT"} { set backendip [getfield [HTTP::uri] "&" 2] set backendip [getfield $backendip "/" 1] HTTP::respond 200 content "Persistence cookie set until browser is closed or cookies are cleared" "Set-Cookie" "F5NODEPERSIST=$backendip; path=/" log "[IP::client_addr]:[TCP::client_port]: New request to [IP::local_addr]:[TCP::local_port] for [HTTP::uri]" return } } else { set activememberslbpool [active_members [LB::server pool] ] } # Use the Host header value for the responses if it's set. If not, use the VIP address. if {[string length [HTTP::host]]}{ set host [HTTP::host] set errhost1 [HTTP::host] set errhost2 [HTTP::host] } else { set host [IP::local_addr] set errhost1 "site" set errhost2 "the site" } #check to see if we match any URI's, to do various things like 503 response, redirect, etc switch [HTTP::uri] { "/maintenance" { if { $activememberslbpool > 0 } { if { $redirectdefaulturlon == 1} { HTTP::redirect http://$host$redirectdefaulturl } else { HTTP::redirect http://$host } } else { HTTP::respond 503 content "Maintenance page \503 - Service temporarily unavailable
\
We are performing routine maintenance designed to improve your $errhost1 experience. \ We will have $errhost2 up again as soon as possible. \ You will be automatically redirected to $errhost2 when it becomes available.
" "Content-Type" "text/html" return } return } "/" { if { $redirectdefaulturlon == 1 } { HTTP::redirect "http://$host$redirectdefaulturl" } return } default { # If the pool is down, redirect to the maintenance page if { $activememberslbpool == 0 } { HTTP::respond 200 content \ " < SCRIPT language=\"JavaScript\"> " } return } } if { $redirectsecureon == 1 } { if { [TCP::local_port] == 80} { HTTP::redirect https://$host[HTTP::uri] return } } } when HTTP_RESPONSE { HTTP::header insert SOURCE_ADDRESS [IP::server_addr] }