Forum Discussion
maintenance page for VIP with different hosts point to different pools if available else redirect to http://$host/maintenance
when HTTP_REQUEST {
sets the timer to return client to host URL set stime 10
Check if the URI is /maintenance switch [HTTP::uri] {
"/maintenance" {
Send an HTTP 200 response with a Javascript meta-refresh pointing to the host using a refresh time
HTTP::respond 200 content \
"Maintenance page\
Sorry! This site is down for maintenance.
" "Content-Type" "text/html" return } } If the respective pool is down, redirect to the maintenance page else send the request to the respective pool if { [ string length [HTTP::host] eq test.com ] && [ active_members test_PROD_V ] < 1 } { log local0. $host HTTP::redirect "http://$host/maintenance" return } else { [ pool test_PROD_V ] } }
but I am getting error 01070151:3: Rule [TEST_IRULE] error: line 20: [wrong args] [string length [HTTP::host] eq test.com ] , can anyone suggested what is wrong with my iRule
6 Replies
- arpydays
Nimbostratus
try "string tolower" instead of "string length"
- VernonWells
Employee
Expanding on @arpydays' answer, the conditional clause is incorrect in a few ways. I'm reproducing your code here in a marked up block with comments after:
when HTTP_REQUEST { sets the timer to return client to host URL set stime 10 Check if the URI is /maintenance switch [HTTP::uri] { "/maintenance" { Send an HTTP 200 response with a Javascript meta-refresh pointing to the host using a refresh time HTTP::respond 200 content \ " \ Sorry! This site is down for maintenance." "Content-Type" "text/html" return } } If the respective pool is down, redirect to the maintenance page else send the request to the respective pool if { [ string length [HTTP::host] eq test.com ] && [ active_members test_PROD_V ] < 1 } { log local0. $host HTTP::redirect "http://$host/maintenance" return } else { [ pool test_PROD_V ] } }You have used the evaluation operator (the square brackets -- [...]) in a number of places where it will have an unintended effect and will produce runtime errors.
To explain, the evaluation operator assumes its contents are a valid Tcl statement and evaluates it, substituting the result of the evaluation in place of the operator. From there, normal Tcl processing continues. So, let's say you do this:
if { [string tolower [HTTP::host]] eq "test.com" } {
the runtime expands inside-out. So, HTTP::host is evaluated first. That command results in a string. Let's say that it yields the value "test.com". If so, after this first expansion, the statement now looks like this:
if { [string tolower test.com] eq "test.com" } {
The remaining evaluation operator is expanded, yielding this:
if { test.com eq "test.com" } {
The runtime then executes the if command. That's what you expect and want. But let's consider your final statement:
[pool test_PROD_V]
This evaluates the pool command, which results in something (I'm not sure what it is, but I'm guessing it's a integer). Let's assume it is an integer. After the expansion, you'll have something like this:
1
Well, the runtime treats every line as a statement. Every statement is a command followed by one or more argument. So, it tries to evaluate the command called "1". There is no such command, so a runtime error is thrown.
It's important to understand that the evaluation operator is not needed to force Tcl to execute a command. Every time Tcl sees a line, it will treat it as a command followed by zero or more arguments. The evaluation operator is only needed when you want to have Tcl evaluate a command that is embedded inside of a statement.
Given all of this, your if clause should look like this:
if { [string tolower [HTTP::host]] eq "test.com" && [active_members test_PROD_V] < 1 } {
and, as I say, your final statement should simply be:
pool test_PROD_V
- rajeshgoud
Altostratus
Thanks Vernon, yes...I corrected them but the issue was when I added additional host header I site is inaccessible
- Stanislas_Piro2
Cumulonimbus
Another point to simplify the configuration. use relative links in redirect instead of absolute if it is on the same Web service...
Replace :
HTTP::redirect "http://$host/maintenance"
By :
HTTP::redirect "/maintenance"
And with the auto refresh in the javascript, redirect to the previous URL for a better user experience..
when HTTP_REQUEST { Check if the URI is /maintenance switch [HTTP::uri] { "/maintenance" { sets the timer to return client to host URL set stime 10 Send an HTTP 200 response with a Javascript meta-refresh pointing to the host using a refresh time HTTP::respond 200 content \ " \ Sorry! This site is down for maintenance." "Content-Type" "text/html" return } } If the respective pool is down, redirect to the maintenance page else send the request to the respective pool if { [ string length [HTTP::host] eq test.com ] && [ active_members test_PROD_V ] < 1 } { log local0. $host HTTP::redirect "http://$host/maintenance?uri=[HTTP::uri]" return } else { pool test_PROD_V } }The following irule is one configured for some customers:
when HTTP_REQUEST { switch [HTTP::path] { "/maintenance/logo.png" { HTTP::respond 200 content [ifile get "logo.png"] "Content-Type" "image/png" return } "/maintenance/maintenance.html" { HTTP::respond 200 content [ifile get "maintenance.html"] "Content-Type" "text/html" return } "/maintenance/error.html" { HTTP::respond 200 content [ifile get "error.html"] "Content-Type" "text/html" return } default { set dpool [LB::server pool] if { $dpool equals "" } { HTTP::redirect "/maintenance/error.html" ; unset dpool; return} if { [active_members $dpool] == 0 } { HTTP::redirect "/maintenance/maintenance.html"; unset dpool; return} unset dpool } } } when HTTP_RESPONSE { if { [HTTP::status] eq "404" } { HTTP::redirect "/maintenance/error.html" } } - Stanislas_Piro2
Cumulonimbus
Do you mean this irule ?
when HTTP_REQUEST { Check if the URI is /maintenance switch [HTTP::uri] { "/maintenance" { sets the timer to return client to host URL set stime 10 Send an HTTP 200 response with a Javascript meta-refresh pointing to the host using a refresh time HTTP::respond 200 content \ " \ Sorry! This site is down for maintenance." "Content-Type" "text/html" return } } If the respective pool is down, redirect to the maintenance page else send the request to the respective pool if { [ active_members [LB::server pool] ] < 1 } { log local0. $host HTTP::redirect "/maintenance?uri=[HTTP::uri]" return } } - rajeshgoud
Altostratus
Hi All, Thank you for the reply, since I am using multiple host to pool iRule, I used the fallback host option to redirect to maintenance page by creating a maintenance VIP on the Load balancer. Thanks and Regards Rajesh Goud M
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com