Technical Forum
Ask questions. Discover Answers.
cancel
Showing results for 
Search instead for 
Did you mean: 

Help with irule using switch

veredgfbll
Altocumulus
Altocumulus

I need an irule that does the following -

If host name equals xxx.com and uri equals /yyy redirect to xxy.com....

but I need to switch between 6 different URIs - I want to use the SWITCH command but I'm not sure how to combine it with the first condition... (The host is constant).

Thanks

2 ACCEPTED SOLUTIONS

Paulius
MVP
MVP

@veredgfbll I believe what you're looking for is the following. Please keep in mind that you do not have to have the final else or the default action in the switch statement and these are just options if by chance you do have a default action you want to perform for the if statement if it doesn't match or the URI path for the single host match.

when HTTP_REQUEST priority 500 {

    set URI [string tolower [HTTP::uri]]

    if { [HTTP::host] == "xxx.com" } {
        switch -- ${URI} {
            "/yyy" {
                # can change http to https if you need to redirect to HTTPS instead
                HTTP::redirect "http://xxy.com/"
            }
            "uri_2" {
                # URI 2 action to execute
            }
            "uri_3" {
                # URI 3 action to execute
            }
            "uri_4" {
                # URI 4 action to execute
            }
            "uri_5" {
                # URI 5 action to execute
            }
            "uri_6" {
                # URI 6 action to execute
            }
            default {
                # default action to perform if URI doesn't match
            }
        }
    } else {
        # action to perform if HTTP::host doesn't match
    }

}

 

View solution in original post

@veredgfbll The iRule you created can be configured as the following which you will notice the "default" match is completely removed since you don't want to perform any other action other than what the iRule and virtual server will already do if a match isn't found.

when HTTP_REQUEST priority 500 {

    set URI [string tolower [HTTP::uri]]

    if { [HTTP::host] == "www.hostname.com" } {
        switch -- ${URI} {
            "/aaa" {
                HTTP::respond 302 Location "https://www.test.com/aaa"
				#log local0. "redirect to https://www.test.com2/aaa completed"
            }
            "/aab" {
                HTTP::respond 302 Location "https://www.test.com/aab"
				#log local0. "redirect to https://www.test.com2/aab completed"
            }
            "/aac" {
                HTTP::respond 302 Location "https://www.test.com/aac"
				#log local0. "redirect to https://www.test.com2/aac completed"
            }
            "/aad" {
                HTTP::respond 302 Location "https://www.test.com/aad"
				#log local0. "redirect to https://www.test.com2/aad completed"
            }
            "/aae" {
                HTTP::respond 302 Location "https://www.test.com/aae"
				#log local0. "redirect to https://www.test.com2/aae completed"
            }
            "/aaf" {
                HTTP::respond 302 Location "https://www.test.com/aaf"
				#log local0. "redirect to https://www.test.com2/aaf completed"
            }
			"/aag" {
                HTTP::respond 302 Location "https://www.test.com/aag"
				#log local0. "redirect to https://www.test.com2/aag completed"
            }
        }
    }

}

View solution in original post

10 REPLIES 10

Paulius
MVP
MVP

@veredgfbll I believe what you're looking for is the following. Please keep in mind that you do not have to have the final else or the default action in the switch statement and these are just options if by chance you do have a default action you want to perform for the if statement if it doesn't match or the URI path for the single host match.

when HTTP_REQUEST priority 500 {

    set URI [string tolower [HTTP::uri]]

    if { [HTTP::host] == "xxx.com" } {
        switch -- ${URI} {
            "/yyy" {
                # can change http to https if you need to redirect to HTTPS instead
                HTTP::redirect "http://xxy.com/"
            }
            "uri_2" {
                # URI 2 action to execute
            }
            "uri_3" {
                # URI 3 action to execute
            }
            "uri_4" {
                # URI 4 action to execute
            }
            "uri_5" {
                # URI 5 action to execute
            }
            "uri_6" {
                # URI 6 action to execute
            }
            default {
                # default action to perform if URI doesn't match
            }
        }
    } else {
        # action to perform if HTTP::host doesn't match
    }

}

 

Hi, This seems good - can I use the "return" command as the default option? (I'd rather have an option to continue as normal)... not quite sure what the default means here... is it like the else option?

Like this?

when HTTP_REQUEST {
    if {[HTTP::has_responded]} { return }
    set URI [string tolower [HTTP::uri]]
    if { [HTTP::host] == "www.hostname.com" } {
        switch -- ${URI} {
            "/aaa" {
                HTTP::respond 302 Location "https://www.test.com/aaa"
				#log local0. "redirect to https://www.test.com2/aaa completed"
            }
            "/aab" {
                HTTP::respond 302 Location "https://www.test.com/aab"
				#log local0. "redirect to https://www.test.com2/aab completed"
            }
            "/aac" {
                HTTP::respond 302 Location "https://www.test.com/aac"
				#log local0. "redirect to https://www.test.com2/aac completed"
            }
            "/aad" {
                HTTP::respond 302 Location "https://www.test.com/aad"
				#log local0. "redirect to https://www.test.com2/aad completed"
            }
            "/aae" {
                HTTP::respond 302 Location "https://www.test.com/aae"
				#log local0. "redirect to https://www.test.com2/aae completed"
            }
            "/aaf" {
                HTTP::respond 302 Location "https://www.test.com/aaf"
				#log local0. "redirect to https://www.test.com2/aaf completed"
            }
			"/aag" {
                HTTP::respond 302 Location "https://www.test.com/aag"
				#log local0. "redirect to https://www.test.com2/aag completed"
            }
            default {
                # default action to perform if URI doesn't match
				return
            }
        }
    } 
}

Thanks

@veredgfbll You can do that but you don't have to because the default action without defining a section called "default" would be to proceed as normal. This applies to the else in an if else statement, if you didn't define an else action the iRule would continue on as normal.

Just to clarify - I can leave the default empty?

The default you would use if you want something 'special to occur'. For example, you can include a log statement to indicate the irule executed but didnt match on any URIs. You can also give the user a block page or whatnot. If nothing is being done, it is not needed. At that point, if nothing matches the switch statement, then the HTTP connection will work as configured on the Virtual Server... passing the HTTP request to a LB selected pool member. Also, if you are ALWAYS redirecting and dont host anything via Pool Members here, you can also do a HTTP respond 200 with a custom error message to return to the user.

Also, good idea on normalizing the URL to all lowercase and then performing the comparison. Many people miss that 😉

so I can remove this bit?

default {
                # default action to perform if URI doesn't match
				return
            }

 

In your particular application, that code doesnt do anything.

@veredgfbll The iRule you created can be configured as the following which you will notice the "default" match is completely removed since you don't want to perform any other action other than what the iRule and virtual server will already do if a match isn't found.

when HTTP_REQUEST priority 500 {

    set URI [string tolower [HTTP::uri]]

    if { [HTTP::host] == "www.hostname.com" } {
        switch -- ${URI} {
            "/aaa" {
                HTTP::respond 302 Location "https://www.test.com/aaa"
				#log local0. "redirect to https://www.test.com2/aaa completed"
            }
            "/aab" {
                HTTP::respond 302 Location "https://www.test.com/aab"
				#log local0. "redirect to https://www.test.com2/aab completed"
            }
            "/aac" {
                HTTP::respond 302 Location "https://www.test.com/aac"
				#log local0. "redirect to https://www.test.com2/aac completed"
            }
            "/aad" {
                HTTP::respond 302 Location "https://www.test.com/aad"
				#log local0. "redirect to https://www.test.com2/aad completed"
            }
            "/aae" {
                HTTP::respond 302 Location "https://www.test.com/aae"
				#log local0. "redirect to https://www.test.com2/aae completed"
            }
            "/aaf" {
                HTTP::respond 302 Location "https://www.test.com/aaf"
				#log local0. "redirect to https://www.test.com2/aaf completed"
            }
			"/aag" {
                HTTP::respond 302 Location "https://www.test.com/aag"
				#log local0. "redirect to https://www.test.com2/aag completed"
            }
        }
    }

}

Thank you very much for clarifying this

whisperer
Cumulonimbus
Cumulonimbus

Well, each time the iRule triggers on the HTTP access, the http request method is triggered. For each trigger or request, the hostname and path would be static. So, why not perform the following:

- Combine the host header and URL bits into a normalized string. Store this in a variable you declare.

- Use the switch statement, and perform a test against this variable. Please see https://community.f5.com/t5/technical-articles/irules-101-04-switch/ta-p/283316.