Varnish VCL, Inline C and a random image
While working with the prototype of a site, I wanted to have a particular panel image randomly chosen when the page was viewed. While this could be done on the server side, I wanted to move this to Varnish so that Varnish’s cache would be used rather than piping the request through each time to the origin server.
At the top of /etc/varnish/default.vcl
C{ #include <stdlib.h> #include <stdio.h> }C
and our vcl_recv function gets the following:
if (req.url ~ "^/panel/") { C{ char buff[5]; sprintf(buff,"%d",rand()%4); VRT_SetHdr(sp, HDR_REQ, "\010X-Panel:", buff, vrt_magic_string_end); }C set req.url = regsub(req.url, "^/panel/(.*)\.(.*)$", "/panel/\1.ZZZZ.\2"); set req.url = regsub(req.url, "ZZZZ", req.http.X-Panel); }
The above code allows for us to specify the source code in the html document as:
<img src="/panel/random.jpg" width="300" height="300" alt="Panel Image"/>
Since we have modified the request uri in vcl_recv before the object is cached, subsequent requests for the same modified URI will be served from Varnish’s cache, without requiring another fetch from the origin server. Based on the other VCL and preferences, you can specify a long expire time, remove cookies, or do ESI processing. Since the regexp passes the extension through, we could also randomly choose .html, .css, .jpg or any other extension you desire.
In the directory panel, you would need to have
/panel/random.0.jpg /panel/random.1.jpg /panel/random.2.jpg /panel/random.3.jpg
which would be served by Varnish when the url /panel/random.jpg is requested.
Moving that process to Varnish should cut down on the load from the origin server while making your site look active and dynamic.
January 11th, 2012 at 11:28 am
Modified to add vrt_magic_string_end as per Christopher Cato’s debugging and DocWilco in IRC