Вы находитесь на странице: 1из 3

iRule Recipe 1: Single URL Explicit Redirect

Vernon 97235, 2019-13-05

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/abc will be explicitly redirected to http://www.new-example.com/abcd. If the Virtual Server
includes the clientssl profile -- which means the Virtual Server is offloading TLS/SSL -- then the Location value in this iRule should
be changed to https://www.new-example.com/abcd. This is a simple iRule, and is intended to solve a simple problem.

iRules 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::hostretrieves the value of the Host header (if one isn't present, then it is the empty string), while HTTP::path returns the
path part of the Request Target (see below for a bit more detail on this). The string tolower is needed for the Host header,
because hostnames are case-indifferent. That is, www.example.com is the same name as wWw.ExAmPlE.cOm and the name can
be expressed either way (and, of course, many other ways besides). string tolower transforms all letters in the text that follows
(HTTP::host, in this case) to all lower-case. By normalizing case, we can reliably compare its value.

Notice that I do not use string tolower on the HTTP::path The HTTP RFC says that the Request Target (including the path) is
case-sensitive. This can get a bit messy because many web servers simply pass the path to the underlying filesystem, which may or
may not be case-sensitive. However, assuming that your web server honors this requirement, then /some/path is not the same as
/SOME/path, for example, so normalizing case is not only not valuable, it is not correct.

One more interesting point: there is an HTTP::redirect iRules command. Why didn't I just use that instead of HTTP::respond?
HTTP::redirect uses a 302 Response Code. 302 is a Temporary Redirect, which encourages the user-agent to try and use the
original URL on subsequent requests. Moreover, many user-agents improperly implemented the 301 (transforming any HTTP
method to a GET on the redirect). Most of the time, what you mean is a Permanent Redirect, which tells the user-agent not to try
the original URL again. Perhaps it would have been better if HTTP::redirect used 301, or at least allowed you to specify which
Response Code you wished, but alas, it does neither.

Elaboration

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/path is the HTTP Request path, here=there&this=that is the HTTP query parameter set, and #section1 is
the fragment. This is transformed into an HTTP Request message that starts like this:

GET /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=that) is called the Request Target. Originally,
the RFCs called it the Request URI. This is confusing because a fully-qualified URL is an instance of a URI, but subsets of a URL
are not. So really, while http://www.example.com/some/path is a URI (and a URL), /some/path is not. iRules uses
HTTP::uri to retrieve the Request Target, because again, that part used to be called the Request URI. But don't get caught:
HTTP::uri does not return the complete URL/URI.

Notice that the fragment (#section1) is not transmitted. A fragment has meaning only to the user-agent, and is a hint about where
to center a rendered document.

How 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 tmsh.

F5 Networks, Inc. | 401 Elliot Avenue West, Seattle, WA 98119 | 888-882-4447 | f5.com

F5 Networks, Inc. F5 Networks F5 Networks Ltd. F5 Networks

Corporate Headquarters Asia-Pacific Europe/Middle-East/Africa Japan K.K.

info@f5.com apacinfo@f5.com emeainfo@f5.com f5j-info@f5.com

©2019 F5 Networks, Inc. All rights reserved. F5, F5 Networks, and the F5 logo are trademarks of F5 Networks, Inc. in the U.S. and in certain other
countries. Other F5 trademarks are identified at f5.com. Any other products, services, or company names referenced herein may be trademarks of
their respective owners with no endorsement or affiliation, express or implied, claimed by F5. CS04-00015 0113

Вам также может понравиться