For more information regarding the security incident at F5, the actions we are taking to address it, and our ongoing efforts to protect our customers, click here.

Forum Discussion

rajeshgoud's avatar
rajeshgoud
Icon for Altostratus rankAltostratus
Mar 09, 2016

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

  • 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's avatar
      rajeshgoud
      Icon for Altostratus rankAltostratus
      Thanks Vernon, yes...I corrected them but the issue was when I added additional host header I site is inaccessible
  • 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" }
    }
    

     

  • 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 
        }
    }
    

     

  • 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