Architectural heads-up/call for comments

Poul-Henning Kamp phk at
Wed Jan 6 12:46:07 CET 2010

This email is sort of an architectural heads-up and a call for
comments from the users of varnish, on a number of ideas I have on
my Todo list right now.

This is not the entire Todo list, but the list of things which
significantly change the way Varnish works today.

New stuff, new features (such as cookie access) are not on this
list, because they have no backwards-compat issues.

The items are ordered for dependency and readability, and thus,
to some extent is indicative of the order things will happen.

1.  Kill the magic default VCL.

What this means for you:

You will no longer be able to just give Varnish a subset of the VCL
instruction, ie. just a vcl_recv{} function, you will have to copy
the default VCL file and modify as needed, and provide varnish all
the mandatory VCL functions.

Why do we want this change:

The current behaviour does not work the way it was intended and
confuses a lot of people, because they do not see the full picture.

The fact that users can provide only function prefixes (which the
default VCL supplements) means that users tend to overlook the
order things have to happen.

For instance supplying a VCL of just:

		sub vcl_recv {
			if {req.url ~ "foobar"} {
				unset req.http.cookie;

Will remove cookies from both GET, POST and any other HTTP command,
because the check if POST should be pass'ed, happens afterwards
in the hidden default VCL.

By forcing the user to edit the default VCL, the check for "POST"
will be visible in the users editor, prompting the user to think
about this aspect.

Why did we get it wrong initially ?

Back in the ancient mists of time, spirits were brave, stakes were
high and we thought it would be possible for users to use VCL
"libraries" and have a VCL file that looked like:
	include "typo3.vcl";
	include "anti_dos.vcl";
	include "anti_malware.vcl";
Obviously, that does not work, because of the ordering necessary
of the checks..

2.  Client identity

What do you mean client identity ?

Think about a feature like sticky sessions:  "we want the same
client to hit the same backend all the time".  That's easy to
understand until you try to find out what people mean with
"same client".   "Client identity" is the handle I use for
the answer to that question.

Since different users answer it different ways, client identity
needs to be controlled by VCL.

For instance, if you have your varnish behind a load-balancer you
will want to use the X-Forwarded-For header to identify your client,
rather than the remote IP#.

But if you are not behind a load-balancer, do you want to pay
attention to the X-Forwarded-For header from a random squid proxy
in Elbonia ?   Probably not.

How will it work ?

I think they way it will work is that we introduce a client.ident
variable in VCL, which starts out the same as client.ip.

Then in vcl_recv{}, you can choose to use X-F-F instead by:

	if (req.http.x-forwarded-for) {
		set client.ident = req.http.x-forwarded-for;

But since client.ident is a string variable, you could also:

	if (req.cookie[USERNAME] {
		set client.ident = req.cookie[USERNAME];

The directors, random/round-robin etc, will then take
whatever value you have put in client.ident, and use that
to implement session-stickyness, however they decide to
do that.

The final bit of this, is that the outgoing X-F-F header will be
produced in VCL, so you get to decide what to put into
it, or if you prefer to adopt the incoming X-F-F instead.

3. Synth replies (and vcl_error{} ?)

I want to make it possible to produce a synthetic reply anywhere
in VCL, with a syntax something like:

	sub vcl_recv {
		if {req.http.diediedie) {
			synth -status 400 -txt "Verdamt!" {"
				<HTML blablabla>

I also want to make it possible to suck in the synth body from a
file, something like:

	sub vcl_recv {
		if {req.http.diediedie) {
			synth -status 400 -txt "Verdamt!" -file "argh.html";

(The file will be read at compile-timer!)

I am not 100% sure we have any need for vcl_error{} after this change,
that needs to be figured out.

4. VCL conversions

In VCL everything is a string, unless it is not.  Sometimes we need
numbers, sometimes we need IP numbers.

I want to make conversions explicit in VCL and it will look something

	sub vcl_recv {
		if (ip(req.http.x-forwarded-for, ~ acl_badguys)) {
			synth -status 503 -txt "bugger off!";

	sub vcl_fetch {
		beresp.ttl = duration(beresp.http.myttl, 10s);

If the conversion fails because the string value is not a valid
IP/time/duration, the second parameter gets used instead.

Thanks for listening, now it's your turn to tell me if this is


Poul-Henning Kamp       | UNIX since Zilog Zeus 3.20
phk at FreeBSD.ORG         | TCP/IP since RFC 956
FreeBSD committer       | BSD since 4.3-tahoe
Never attribute to malice what can adequately be explained by incompetence.

More information about the varnish-misc mailing list