Vmod-dbrw is a Varnish Cache module implementing database-driven rewrite rules. It is intended for use with web sites that need an exceedingly big number of redirects and/or rewrites. Vmod-dbrw allows you to keep all rules in an SQL database of arbitrary structure, considerably speeding up their handling. Another advantage of this approach is that rewrite rules stored in a database are easier to maintain.

Two database are supported: MySQL and PostgreSQL. The module works with Varnish versions from 4.1 to 6.0.2.

The following quick-start example should give you a feel for how it works and what can be done with it. For more examples, please refer to the documentation section.

This example expects the rules to be stored in a table of the following structure:

CREATE TABLE rewrite (
  host varchar(255) NOT NULL DEFAULT '',    -- Host name part of the incoming request
  url varchar(255) NOT NULL DEFAULT '',     -- URL part of the incoming request
  dest varchar(255) DEFAULT NULL,           -- URL to redirect to if this row matches
  value varchar(255) DEFAULT NULL,          -- Additional condition
  pattern varchar(255) DEFAULT NULL,        -- Regular expression to match against value 
  KEY source (host,url)
)

First of all, import the necessary Varnish modules.

import dbrw;

The call to dbrw.config function informs the module about the type of database to use, access credentials and its structure. It is normally called from vcl_recv:

sub vcl_recv {
        dbrw.config("mysql",
	            "server=db.example.com;database=varnish;user=varnish;password=guessme",
                    {"SELECT dest,pattern,value FROM rewrite
                      WHERE host='$host'
                      AND url IN ($(urlprefix $url))
                      ORDER BY LENGTH(url) DESC"});
}

The structure is described via a query supplied in the 3rd argument. The variable references $host and $url will be replaced with the actual values later.

The function dbrw.rewrite does the actual job:

sub vcl_recv {
    set req.http.X-Redirect-To =
	    dbrw.rewrite("host=" + req.http.Host + ";" +
                         "url=" + req.url);
    if (req.http.X-Redirect-To != "") {
	return(synth(301, "Page moved"));
    }
}

Its argument supplies actual values for the variables used in the query. The expanded query is sent to the database server and for each tuple it returns the content of the value column is matched against pattern, which is treated as an extended POSIX regular expression. Before comparing the value column undergoes variable expansion, using the values supplied in the argument to dbrw.rewrite. If it matches the pattern, the rewrite function returns the value of the dest column, with eventual backreferences expanded.

The sub vcl_synth forms the redirection response:

sub vcl_synth {
    if (resp.status == 301) {
        set resp.http.Location = req.http.X-Redirect-To;
        return (deliver);
    }
}