Thursday, January 27, 2011

Browser - Server Communication(Http Caching)

Hi, Recently I had faced a very common web app problem...and there are few interesting things to share with..

User Profile page - where User can upload an Image and can change If he wants.. and to upload the Image we made an Action class to respond.. and the thing is the Url is static.. thus causes the Problem..
Even though the User is Changing the Picture the browser displays the Old picture(Edit -> View)..Post to Get ..the url to fetch the Image is static the actual request to Fetch the Picture is not Fired..the browser simply fetches the Image from the Cache..Unless If we manually refresh the page..

Two things to note down here.. Either
a) we can tell the browser not to use the Cache or
    * 1 Option One: Use a Cache-Control Header with 's-maxage'
    * 2 Option Two: Use a Query String
    * 3 Option Three: Use a "Zero" Expires Header
    * 4 Option Four: Use a Cache-Control Header with 'private'
    * 5 Option Five: Use a Cache-Control Header with 'no-cache'
    * 6 Option Six: Use a Cache-Control Header with 'no-store'
b) use the cache for may be for some period of time..
* 1 Use a Cache-Control Header with 'maxage' with time period specified.
Problem with option a) is the performance hit..Every time a new request made eventhough the picture is not actually changed by the User.

Problem with option b) If user changes the Picture the Browser uses the Cached version. Oops...

Is there a way to tell the Browser, If the Picture modified at the Server side use the updated one If not use the one in Cache..Oh this is been the perfect solution, If it can be achieved.. !
 So we need to communicate with the browser.. the only way via through the HTTP response..
The Browser will normally Interpret the response and initiate a new request..

The Http Response Header which suits very close is "max-age=0"

max-age=0 implies that the content is considered stale (and must be re-fetched) immediately

It can be used by either by the Browser(via Request) or by the Server (via Response)

When "max-age=0" added in Response Header by the Server It simply tells caches/Browsers  the response is stale from the get-go and so they SHOULD revalidate the response before using a cached copy. ( I tried this option with Mozilla/IE8 but both are not performing any Validation and it causes a new request Every time..It's simply behaves like not using the Cache.)

When "max-age=0" added in Request Header by the Browser , then each cache along the way will revalidate its cache entry (eg. with the "If-Not-Modified" header) all the way to the origin server. If the reply is then 304 (Not Modified), the cached entity can be used.Else If it's 200(Modified), Use the Updated one.

When sent by the Browser: Request Header with "max-age=0"


Response From Server with Status Code :



So...the Browser uses "max-age=0" in the Request Header the Server responds with proper status code(304/200) and the Cache entries are used accordingly.

If Server uses "max-age=0" in response Header  "response.setHeader("Cache-control","max-age=0");" the Browser always makes a new request to the Server...may be can avoid the actual download cost by using server side logic, but not the overhead an additional Http Call to the Server!!!