HAProxy bulk redirects

Table of Contents

1 Overview

Lua library for handling big amounts of redirect rules in HAProxy.

2 Introduction

The traditional way of implementing redirects in HAProxy configuration file is by using the http-request redirect statement. It is quite OK for a couple of redirect rules. Sometimes, however, you need to install thousands of redirects. This may be necessary, for instance, when switching to a new version of a site, in order to preserve old references. Keeping such a big number of redirect statements in the configuration file is impractical, and maintaining such a configuration is tedious and error-prone task.

The haproxy-bulkredirect library is designed for such cases. It reads redirection rules from a plain text file, which is easy to maintain. Internally, the rules are stored in an associative array, which provides for fast lookups.

3 Dependencies

HAProxy version 2.3.6 or newer, compiled with Lua support.

4 Installation

Copy the file bulkredirect.lua to a directory on the server where the haproxy server runs. Load it in the global section of your configuration file:

global
   lua-load /DIR/bulkredirect.lua

(replace DIR with the actual location on the filesystem).

In your frontend section, add the following statement:

http-request lua.bulkredirect

Write down your redirection rules to the file /etc/haproxy/bulkredirect.rt (see below for detailed instructions). If you prefer another file name, make it known to the library using the HAPROXY_BULKREDIRECT environment variable. When done, restart haproxy.

5 Redirection table

By default, the library reads redirection table from the file /etc/haproxy/bulkredirect.rt. Another file name can be supplied via the HAPROXY_BULKREDIRECT environment variable.

Each line in a redirection table file is either a comment or a statement. A comment begins with a # character as first non-whitespace character in the line and extends to the end of the line. Comments serve as human-readable annotations and are otherwise ignored. Empty lines are ignored as well.

There are three kinds of statements: option definition, domain declaration, and redirection rule.

5.1 Option definition

Option definition begins with the word option followed by one or more option names, delimited with commas. Valid option names are:

  • www

    Declares that rules for each domain name declared below apply also for that domain name, prefixed with www.

    Similarly, if a domain name already begins with www., all rules defined for it apply also for a domain name with the www. prefix removed.

  • exact

    By default, all redirects imply prefix search. That is, if you declare redirect rule from /foo to /bar, it would also apply to /foo/bay, which would be redirected to /bar/bay, etc.

    If the exact option is set, no path prefix search is done: the redirection is triggered only when the pathname part of the URL matches exactly the left-hand side of a redirection rule.

  • strippath

    When set, removes from the final URL the pathname components stripped off during prefix search. For example, given a redirect rule from /foo to /bar, the URL /foo/bay/qux will be redirected to /bar as well.

  • stripquery

    Discard any query string attached to the incoming URI.

  • temporary

    Creates a temporary redirect (HTTP response code 302). By default, permanent redirects (301) are created.

  • urlencode

    Encode special characters in path parts of both source and destination URLs as specified in RFC 3986 ("percent encoding"). By default, bulkencode assumes all URLs are already properly encoded.

Each of these option names can be prefixed with no to revert its meaning.

By default all options are unset.

The options defined in this statement remain in effect until changed by another option statement below. They also can be overridden for each redirect individually. See the discussion of redirection rules below.

Here is an example of the option statement:

option www,stripquery

5.2 Domain declaration

This statement declares a domain for which the redirection rules below apply. Syntactically, it is:

[DOMAIN]

where DOMAIN is the domain name. No whitespace is allowed between the name and square brackets.

If the lua-idna library is available, the DOMAIN can be a UTF-8 string. It will be converted to the appropriate ASCII form automatically.

Each domain declaration remains in effect until another domain declaration is encountered in the redirection table.

Special name "*" means "any domain name".

5.3 Redirection rule

A redirection rule consists of two parts separated by arbitrary amount of whitespace. The left-hand side of the rule supplies the URI in the current domain and the right-hand side gives the URL to redirect it to. Examples

/about  	            /info
/pager?q=10&confirm=true  https://example.com/pages

Left-hand side may contain query part, as shown in the last example. Notice, that the query part is matched verbatim, which means that, e.g. /pager?confirm=true&q=10 won't be redirected.

If the query part is present in the right-hand side, it will replace the actual query (i.e. the stripquery option is enabled automatically). It will also enable the strippath option for this redirect.

A question mark without query part in the destination silently enables both stripquery and strippath options for this redirect.

To override options for a single redirect, supply them after the destination using the same syntax as in option statement. For example:

/about	/info  exact,www

6 Test suite

A test suite is included in the distribution. The following utilities are needed for testing: curl, egrep, and nc. To run the test, change to the directory t/ and run:

./testsuite

By default this will start a copy of haproxy listening on localhost port 8080, if this port is available. If not, you will need to select an unused TCP port and supply its number with the -p option, e.g.:

./testsuite -p 8081

Upon termination the testsuite tool prints total number of tests run and number of failed tests. In case of failure, the information about each failed test is preserved in the directory testsuite.dir/N, where N is the test number. If you encounter any failures, please create a tar archive of the testsuite.dir directory and send it to the author.

7 Bug reports

Please, send bug reports and suggestions to Sergey Poznyakoff.

8 Copyright

Copyright (C) 2021 Sergey Poznyakoff

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Author: Sergey Poznyakoff

Created: 2021-03-19 Fri 12:05

Emacs 25.3.1 (Org mode 8.2.10)

Validate