Forum Discussion

Aaron_M__Long_1's avatar
Aaron_M__Long_1
Icon for Nimbostratus rankNimbostratus
Sep 27, 2012

iRule switch confusion (Version 9.4.4)

So I've created an iRule using the switch statement, but for some reason my logic is failing for every conceivable match. Every condition falls through to the default case. What am I doing wrong? Thanks in advance.

 New iRule to protect website storefronts from mischief

when HTTP_REQUEST {

if {[HTTP::uri] starts_with "/storefront/"} {

Do nothing

} else {

switch {[HTTP::uri]} {

"" -

"/" -

"/storefront" { HTTP::respond 301 Location "https://[HTTP::host]/storefront/home.ep" }

"/us.website-sitemap.xml" -

"/uk.website-sitemap.xml" -

"/ca.website-sitemap.xml" -

"/ie.website-sitemap.xml" -

"/au.website-sitemap.xml" -

"/row.website-sitemap.xml" -

"/robots.txt" {}

default { HTTP::respond 301 Location "https://[HTTP::host]/storefront/error.ep?errorCode=404" }

}

}

}

6 Replies

  • Hi Aaron,

     

     

    Try this ,,,

     

     

    when HTTP_REQUEST {

     

    if {[HTTP::uri] starts_with "/storefront/"} {

     

    return

     

    } else {

     

    switch {[HTTP::uri]} {

     

    "" -

     

    "/" -

     

    "/storefront" { HTTP::respond 301 Location "https://[HTTP::host]/storefront/home.ep" }

     

    "/us.website-sitemap.xml" -

     

    "/uk.website-sitemap.xml" -

     

    "/ca.website-sitemap.xml" -

     

    "/ie.website-sitemap.xml" -

     

    "/au.website-sitemap.xml" -

     

    "/row.website-sitemap.xml" -

     

    "/robots.txt" { return }

     

    default { HTTP::respond 301 Location "https://[HTTP::host]/storefront/error.ep?errorCode=404" }

     

    }

     

    }

     

    }

     

  • That change had no effect. The problem doesn't appear to be an issue of the conditional block being executed correctly, it's that the condition isn't matching at all.
  • The curly braces around your switch condition causes it fail.

    
    when HTTP_REQUEST {
        if { [string tolower [HTTP::uri]] starts_with "/storefront/" } {
    log local0. "/storefront/"
    return
             Do nothing
        } else {
            switch [string tolower [HTTP::uri]] {
    "/" -
    "/storefront" {
    log local0. "/storefront"
    HTTP::respond 301 Location "https://[HTTP::host]/storefront/home.ep" 
    }
                "/us.website-sitemap.xml" -
                "/uk.website-sitemap.xml" -
                "/ca.website-sitemap.xml" -
                "/ie.website-sitemap.xml" -
                "/au.website-sitemap.xml" -
                "/row.website-sitemap.xml" -
                "/robots.txt" { 
    log local0. "xml"
    return 
    }
                default {
    log local0. "default"
    HTTP::respond 301 Location "https://[HTTP::host]/storefront/error.ep?errorCode=404" 
    }
            }
        }
    }
    

    You also don't need the "" (empty) condition. It'll never happen.

  • Hi Aaron,

    Try this:

     
    when HTTP_REQUEST {
    switch -glob [string tolower [HTTP::uri]] {
    "/" { HTTP::respond 301 Location "https://[HTTP::host]/storefront/home.ep" }
    "/storefront*" -
    "*/us.website-sitemap.xml" -
    "*/uk.website-sitemap.xml" -
    "*/ca.website-sitemap.xml" -
    "*/ie.website-sitemap.xml" -
    "*/au.website-sitemap.xml" -
    "*/row.website-sitemap.xml" -
    "*/robots.txt" { return }
    default { HTTP::respond 301 Location "https://[HTTP::host]/storefront/error.ep?errorCode=404" }
    }
    }
    

    Your first conditional if statement is to do nothing if the [HTTP::uri] starts with "/storefront/", but you have the same condition within your switch statement to redirect it, so I removed removed it and set the condition to only redirect if the [HTTP::uri] is "/" and collapsed the if statement.

    In a switch statement you can "string tolower" the [HTTP::uri] value to set the comparison condition to a known state for comparison, add the "-glob" can be added so that you can utilize Wildcards. These together should get you the matches and actions that you are looking for.

    All values in the switch statement are absolute unless you utilze a Wildcard as well. You can narrow down what your looking for like this:

    starts_with = "/something*"

    ends_with = "*/something.html"

    contains = "*something*"

    The "-" on the ends tells the condition to respond the same way as the next item, so you only have to type the action once. So all of your "/storefront", XML matches, and the robots.txt will break out of the switch statement and perform no action, but successfully prevent the default redirect.
  • Thanks, +Kevin Stewart, it was the braces that was killing my match condition.

     

     

    I hadn't realized that the null match would never get hit. Am I to take it that F5 interprets 'http://website.example.com' and 'http://website.example.com/' identically, and that [HTTP::uri] will return '/' for both?
  • It's actually a function of the browser and the HTTP protocol. Your browser will implicitly add the "/" to your request if you don't supply a path. In fact the protocol requires a path in the HTTP method statement (ex. GET / HTTP/1.1)

     

     

    RFC 2616 states (http://www.ietf.org/rfc/rfc2616.txt):

     

     

    "If the abs_path is not present in the URL, it MUST be given as "/" when used as a Request-URI for a resource (section 5.1.2)"

     

     

    That's why you'll never see a request with an empty path.