Mobile redirects using Varnish

Our loadbalancers TMM has gone up quite a bit lately, so I started looking into how to move some of the workload to Varnish instead. I came across this configexample and pulled out the mobile redirects part. It’s a rather dirty hack, but it works. Varnish does not have support of HTTP redirects, so you have to trigger an error and then pick it up in the vcl_error subroutine later.
This is what the redirect-config looks like on my test-system :

sub vcl_recv {
if ( req.http.user-agent ~ "(.*Blackberry.*|.*BlackBerry.*|.*Blazer.*|.*Ericsson.*|.*htc.*
|.*Huawei.*|.*iPhone.*|.*iPod.*|.*MobilePhone.*|.*Motorola.*|.*nokia.*
|.*Novarra.*|.*O2.*|.*Palm.*|.*Samsung.*|.*Sanyo.*|.*Smartphone.*
|.*SonyEricsson.*|.*Symbian.*|.*Toshiba.*|.*Treo.*|.*vodafone.*
|.*Xda.*|^Alcatel.*|^Amoi.*|^ASUS.*
|^Audiovox.*|^AU-MIC.*|^BenQ.*|^Bird.*|^CDM.*|^DoCoMo.*|^dopod.*
|^Fly.*|^Haier.*|^HP.*iPAQ.*|^imobile.*|^KDDI.*|^KONKA.*|^KWC.*
|^Lenovo.*|^LG.*|^NEWGEN.*|^Panasonic.*|^PANTECH.*|^PG.*|^Philips.*
|^portalmmm.*|^PPC.*|^PT.*|^Qtek.*|^Sagem.*|^SCH.*|^SEC.*|^Sendo.*
|^SGH.*|^Sharp.*|^SIE.*|^SoftBank.*|^SPH.*|^UTS.*|^Vertu.*
|.*Opera.Mobi.*|.*Windows.CE.*|^ZTE.*)"
&& req.http.host ~ "(www.somehost.com)"
&& req.url == "/") {
set req.http.newhost = regsub(req.http.host, "(www)?\.(.*)", "http://m.\2");
error 750 req.http.newhost;
}


sub vcl_error {
if (obj.status == 750) {
set obj.http.Location = obj.response;
set obj.status = 302;
deliver;
}
}

Tags: , ,

Using Varnish ESI to include content from another host

I want to include a .html element from otherhost.com on my website. This is how to do it With ESI (Edge Side Include) in varnish:
On my webserver i have index.html. Inside this document i want to include externalcontent.html from otherhost.com. The html code which varnish needs to interpret looks like this:
<esi:include src="http://otherhost.com/externalcontent.html"/>
In order to make varnish aware of the need to do esi processing you need the following in your varnish config:

1. We need to define otherhost.com as a backend in order for varnish to know that it needs to fetch this content from another host: (the .host part needs to be the ip of the webserver for otherhost.com)
backend otherbackend {
.host = "1.2.3.4";
.port = "80";
}

2. Inside vcl_fetch:
Note: the req.url ~ “whatever” needs to reflect which pages needs esi processing)
if (req.url ~ "index.html") {
esi;
}

3. Inside vcl_recv:
if (req.http.host == "otherhost.com") {
set req.backend = otherbackend;
}

4. Restart varnish and you are done :)
/etc/init.d/varnish restart

Reference:

http://varnish.projects.linpro.no/browser/trunk/varnish-cache/bin/varnishtest/tests/e00006.vtc

Tags: , , , ,

Backporting varnish from debian unstable/testing to etch

Recently i wanted to upgrade Varnish to latest stable – 2.0.4 on our debian etch boxes. Do you think debian has the latest version in the etch repos? Ofcourse not.. However, backporting turned out to be allmost too easy :) Here is how I did it;

1. Edit your /etc/apt/sources.list deb-src entry to reflect which debian version you want to backport packages from. My entry looks like this:
deb-src http://ftp.no.debian.org/debian/ unstable main non-free contrib
2. Download the source code from the repo:
apt-get source varnish
3. Make sure you have all the deps needed:
apt-get build-dep varnish
4. (might not be necessary) I was missing the fakeroot package:
apt-get install fakeroot
5. Build the package(s):
cd varnish-2.0.4
dpkg-buildpackage -rfakeroot -uc -b

6. And finally install your newly created packages:
cd ..
dpkg -i *.deb

Reference(s):
http://www.debian.org/doc/manuals/apt-howto/ch-sourcehandling.en.html

Tags: , , , , , ,

Varnish & Cookies

By default Varnish passes requests with cookies to the backend.

It is not recommended, but in some cases it is necessary to cache requests with cookies too.

This can be done by adding the following to the config file :
sub vcl_recv {
if(req.http.Cookie) {
lookup;
}
}

This might result in some trouble for logged in users who needs unchached content. You can match a cookie and pass it to the backend like this (also inside vcl_recv):

if (req.http.Cookie ~ "yourcookie") {
pass;
}

Instead of the name of the cookie, you could also use the content of it as Varnish reads the entire cookie header.

Tags: ,