Atlas 7: Caching web service response on browser and save bandwidth significantly

Browser can cache images, javascripts, css files on users hard
drive and it can also cache Xml Http calls if the call is a Http
Get. The cache is based on Url. If it’s the same Url and it’s
cached on the computer then the response is loaded from cache, not
from the server when it is requested again. Basically, browser can
cache any Http Get call and return cached data based on Url. If you
make a Xml Http call as Http GET and server returns some special
header which informs the browser to cache the response; on future
calls, the response will be immediately returned from the cache and
thus save the delay of network roundtrip and download time.

At Pageflakes, we cache
user’s state so that when user visits again the following day, user
gets a cached page which loads instantly from browser cache, not
from the server. Thus second time load becomes very fast. We also
cache several small parts of the page which appears on users
action. When user does the same action again, a cached result is
loaded immediately from local cache and thus saves the network
roundtrip time. User gets a fast loading site and a very responsive
site. The perceived speed increases dramatically.

The idea is to make Http Get calls while making Atlas web
service calls and return some specific Http Response headers which
tells the browser to cache the response for some specific duration.
If you return “Expires” header during the response, browser will
cache the Xml Http response. There are 2 headers that you need to
return with response which will instruct browser to cache the
response:

HTTP/ 1.1 200
OK Expires: Fri , 1
Jan 2030 Cache-Control: public

This will instruct browser to cache the response till Jan 2030.
As long as you make the same Xml Http call with the same
parameters, you will get cached response from the computer and no
call will go to the server. There are more advanced ways to get
further control over response caching. For example, here is a
header which will instruct browser to cache for 60 seconds but do
contact server and get a fresh response after 60 seconds. It will
also prevent proxies from returning cached response when browser
local cache expires after 60 seconds.

HTTP/ 1.1 200
OK Cache-Control: private
, must-revalidate , proxy-revalidate , max-age = 60

Let’s try to produce such response headers from ASP.NET web
service call:

This will result in the following response headers:

Expires header is set properly. But the problem is with
Cache-Control. It is showing “max-age” is set to zero which will
prevent browser from doing any kind of caching. If you seriously
want to prevent caching, you should emit such cache-control header.
Looks like exactly the opposite thing happened.

There’s a bug in ASP.NET 2.0 that you cannot change “max-age”
header. As max-age is set to zero, ASP.NET 2.0 sets Cache-Control
to private because max-age = 0 means no cache needed. So, there’s
no way you can make ASP.NET 2.0 return proper headers which caches
the response.

Time for a hack. After decompiling the code of HttpCachePolicy
class (Context.Response.Cache object’s class), I found the
following code:

Somehow, this._maxAge is getting set to zero and the check: “if
(!this._isMaxAgeSet || (delta < this._maxAge))" is preventing it from getting set to a bigger value. Due to this problem, we need to bypass the SetMaxAge function and set the value of the _maxAge field directly using Reflection.

This will return the following headers:

Now max-age is set to 60 and thus browser will cache the
response for 60 seconds. If you make the same call again within 60
seconds, it will return the same response. Here’s a test output
which shows the date time returned from the server:

The client side code is like this:

function cachedHttpGet() { WebService.CachedGet( {
useGetMethod:
true
, onMethodComplete:
function (result) { debug.dump(result); } } );
}

Here you see, the response is cached for 60 seconds and after
the time elapsed, there was a server call made and new date was
returned. That response was again cached for 60 seconds.

20 thoughts on “Atlas 7: Caching web service response on browser and save bandwidth significantly”

Leave a Reply