Using Varnish to Cache API Requests

#1 - Aug. 28, 2011, 11:47 p.m.
Blizzard Post
Figured this might be useful to anyone out there who is already using Varnish or may use Varnish for their own projects (and you should. Varnish is awesome).

Reasons why it's useful:


  • Varnish is super fast.

  • You can set it up to effectively be a proxy so you can use your own domain to avoid cross-domain AJAX issues.

  • Generally understands HTTP caching and handles most details without worry.


I based my own setup for Raidbots off the masquerading example from the varnish doc pages. This works in Varnish 2.1 and above, I believe (no idea about 3.0 though).

How you use it

Instead of sending a request directly to battle.net, you send your HTTP request (with or without the Authorization header) to your own domain. For example:

http://my-awesome-wow-site.com/wowapi/us/realm/status/

With the API seemingly coming from your own domain, you can easily use the data in AJAX calls without needing to write your own little caching proxy.

Thought it might be useful for any other web nerds out there!

The following VCL code should get you started if you're a Varnish user. If you have an API key and are using the Authorization header, Varnish will pass it on properly.


backend us_wowapi {
.host = "us.battle.net";
.port = "80";
}
backend eu_wowapi {
.host = "eu.battle.net";
.port = "80";
}
backend kr_wowapi {
.host = "kr.battle.net";
.port = "80";
}
backend tw_wowapi {
.host = "tw.battle.net";
.port = "80";
}

sub vcl_recv {
if (req.url ~ "^/wowapi") {
if( req.url ~ "^/wowapi/us" ) {
set req.http.host = "us.battle.net";
set req.url = regsub(req.url, "^/wowapi/us","/api/wow");
set req.backend = us_wowapi;
} else if ( req.url ~ "^/wowapi/eu" ) {
set req.http.host = "eu.battle.net";
set req.url = regsub(req.url, "^/wowapi/eu","/api/wow");
set req.backend = eu_wowapi;
} else if ( req.url ~ "^/wowapi/kr" ) {
set req.http.host = "kr.battle.net";
set req.url = regsub(req.url, "^/wowapi/kr","/api/wow");
set req.backend = kr_wowapi;
} else if ( req.url ~ "^/wowapi/tw" ) {
set req.http.host = "tw.battle.net";
set req.url = regsub(req.url, "^/wowapi/tw","/api/wow");
set req.backend = tw_wowapi;
}
remove req.http.Cookie;
return( lookup );
}
}

sub vcl_fetch {
if( req.http.host == "us.battle.net" ||
req.http.host == "eu.battle.net" ||
req.http.host == "kr.battle.net" ||
req.http.host == "tw.battle.net" ) {
# force 1 day cache on any bnet requests
set beresp.ttl = 86400s;
# clients will check for an update every hour, this will just come from varnish
set beresp.http.Cache-Control = "max-age=3600";
return(deliver);
}
}
Forum Avatar
Web & Mobile Team
#2 - Aug. 29, 2011, 2:40 p.m.
Blizzard Post
This is good. Thanks for posting this.