iRule Recipe 1: Single URL Explicit Redirect
Series Introduction
Let's face it: there aren't many people out there who have extensive experience with Tcl. Since iRules is a Tcl dialect, that means that finding a solid iRules solution can be challenging, even for otherwise experienced coders. And many times, those who architect, configure, troubleshoot and manage BIG-IPs don't normally code as part of their day job. For both groups, most problems can be solved by finding iRules code that tackles a problem similar to one they face, modifying it just a bit to suit the specific need. This series hopes to provide that sort of code: "recipes" that capture patterns used by BIG-IP practitioners to solve common problems.
Each article is a single recipe. The article begins by explaining a problem you might be trying to solve. It then presents an iRule that can solve it. After that, it provides an analysis of the iRule. Finally, it provides a more detailed background section to elaborate on how the supporting protocols work and any nuances regarding the problem or solution.
In some cases, there is a non-iRules method for solving a problem. When this the case, there will be one more section, called "How Else Could I Have Solved This?" This section outlines the alternative solution or solutions.
Recipe 1: Single URL Explicit Redirect
The Problem
You want to respond to a specific HTTP URL with an explicit HTTP Redirect, using a 301 Status Code and the Location header.
The Code
when HTTP_REQUEST {
  if { [string tolower [HTTP::host]] eq "www.example.com" and [HTTP::path] eq "/path1/abc" } {
    HTTP::respond 301 Location "http://www.new-example.com/abcd"
  }
}
Analysis
When this rule is applied to a Local Traffic Virtual Server with the http profile applied, then any request for
www.example.com/path1/abchttp://www.new-example.com/abcdhttps://www.new-example.com/abcdiRules are triggered by events. The set of profiles applied to a Virtual Server determines the events that will fire. If a Virtual Server has the http profile applied, then -- among others -- the HTTP_REQUEST event will fire. It happens when an HTTP Request message is received, and the BIG-IP has completely parsed the Request message headers. Code attached to the HTTP_REQUEST event usually reads headers or the HTTP start-line, and may modify either of them.
HTTP::hostHTTP::pathstring tolowerstring tolowerHTTP::hostNotice that I do not use
string tolowerHTTP::path/some/path/SOME/pathOne more interesting point: there is an
HTTP::redirectHTTP::respondHTTP::redirectHTTP::redirectElaboration
Remember! This section goes into more details about HTTP and how it relates to iRules. I believe it can be quite useful, but if all you needed was the recipe, feel free to skip this section.
HTTP transactions are stateless, and always consist of exactly two messages: a Request message followed by a Response message. Even if more than one transaction is conducted on a single TCP connection (called HTTP KeepAlive), each transaction is, at the level of HTTP, independent from all others.
An HTTP message consists of a start-line, zero or more headers, and a body. For some request message types, the body is empty. With HTTP/1.0, the header set can be empty, but with HTTP/1.1, at least the Host header is required in Request messages, and generally, Response messages always have at least one header.
When a request is made from a user-agent that looks like this:
http://www.example.com/some/path?here=there&this=that#section1
the http is the "scheme" and tells the user-agent how to treat the rest of the URL. www.example.com is sent as the value of the Host header.
/some/pathhere=there&this=that#section1GET /some/path?here=here&this=that HTTP/1.1 Host: www.example.com
The second element of the start-line (that is,
/some/path?here=&there;this=thathttp://www.example.com/some/path/some/pathHTTP::uriHTTP::uriNotice that the fragment (
#section1How Else Could I Have Solved This?
Starting in BIG-IP version 11.4, Local Traffic Policies were introduced. Describing this feature is -- as they say -- outside the scope of this article, but in brief: it's a really cool way to do common HTTP transforms, including redirects. It has the advantage of not being code, and it is part of the built-in feature set. Local Traffic Policies can be modified using the BIG-IP web UI or
tmsh11 Comments
- N__Tariq_149828Nimbostratus Great article. Thanks heaps!!! I believe there is an extra bracket at following location and this is causing syntax error: [HTTP::path] eq "/path1/abc" ] <<< may need to be removed?? 
- VernonWellsEmployee You are naturally quite right. That must have been a cut-and-paste error. The extra square brace has been removed! 
- ManishvashishtaNimbostratus Can someone please validate below iRule? when HTTP_REQUEST { if { [string tolower [HTTP::host]] ends_with ".abc.com" } { HTTP::respond 301 Location "https://eservices-t.abc.com/irj/portal/abc[HTTP::uri]" } if { [string tolower [HTTP::host]] ends_with ".def.com" } { HTTP::respond 301 Location "https://eservices-t.def.com/irj/portal/def[HTTP::uri]" } 
- VernonWellsEmployee How to you mean? The rule looks sensible to me, depending on what you want to achieve. If the Host header contains a name in the abc.com domain, then it will send a redirect to the client to the first request target, appending the original request target to the end. If the Host header contains a name in the def.com domain, then it redirects to the second request target, appending the original again. 
- rsbs01Nimbostratus Hi Vernon. Can I use something similar to redirect multiple URL to one specific URL, let's say https://aaa.bbb.com? 
- VernonWellsEmployee Absolutely. In that case, you could use a 
 or a data-group (usingswitch
 ). I'd recommend, however, that you look into using a Local Traffic Policy. A policy is easy to set up and doesn't require any iRules.classAnyhow, a 
 based approach might look something like this:switchwhen HTTP_REQUEST { switch [string tolower [HTTP::host]] { "abc.com" - "def.com" { switch -glob [HTTP::path] { "/first/second" - "/first/second/*" { HTTP::respond 301 Location "https://aaa.bbb.com/" } } } } }This would redirect any request for abc.com or def.com that has a URI Target path starting with /first/second to ";. 
- rsbs01Nimbostratus Thanks, Vernon. 
- Anthony_1648Nimbostratus Thanks for the article! It was helpful, but I'm still having trouble getting an iRule to work for http redirects. If a user comes with a specific path /newpath I need it redirected to a different site, if the user does not specify the path I need it redirected to another site. This is what I have, but it's not working properly. Any help would be appreciated. when HTTP_REQUEST { if { (([HTTP::host] equals "site.com/newpath") or ([HTTP::host] equals ";)) } { HTTP::redirect "; } else {(([HTTP::host] equals "site.com") or ([HTTP::host] equals ";)) } HTTP::redirect "; } 
- VernonWellsEmployee 
 retrieves the value of the Host header, while the Request-Target path is part of the Request-Target in the HTTP Request Start-Line. Consider a request in your browser URL bar:HTTP::hosthttp://site.com/newpathThis would produce an HTTP Request message similar to the following (I omit a number of likely headers that aren't relevant to this example): GET /newpath HTTP/1.1 Host: site.comNotice that the path element (i.e., 
 ) is in the Request-Line. To extract that, you should use/newpath
 . Thus, to match the URL above, you would do this:HTTP::pathwhen HTTP_REQUEST { switch [string tolower [HTTP::host]] { "site.com" - "www.site.com" { if { [HTTP::path] eq "/newpath" } { HTTP::respond 301 Location "https://www.site2.com/newpath" } } } }I use 
 to reduce the number of evaluations ofswitch
 andHTTP::host
 , but this could also be written:string tolowerif { [string tolower [HTTP::host]] eq "site.com" or [string tolower [HTTP::host]] eq "www.site.com" } { ... }Having said all of this, I strongly recommend that you consider using a Local Traffic Policy. 
- Anthony_1648Nimbostratus Thank you for the response! I am not familiar with using a LTP. I will research further. Thank you!