2

i tried to cache a json response from an api request using the Etag. I'm calling something like this http://localhost:3000/api/config and getting:

Response Headers:
Cache-Control:public, max-age=31557600
Connection:keep-alive
Content-Length:11
Content-Type:application/json; charset=utf-8
Date:Wed, 13 May 2015 11:41:52 GMT
ETag:"94d52736bcd99b1ac771f13b1bbdf622"
X-Powered-By:Express

Resonse: {id: 1}

I expected the browser to cache the response and to send the Etag with the next request triggert by "f5". But this isn't the case.

Request Headers 2nd request:
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8
Accept-Encoding:gzip, deflate, sdch
Accept-Language:de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
Cache-Control:no-cache
Connection:keep-alive
Host:localhost:3000
Pragma:no-cache
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36

So is it impossible to cache pure json response, getting by a direct api requests?
Or do i miss something.

The api is an node js test implemantation done with express:

router.get('/config', function(req, res) {
    var eTag = crypto.createHash('md5').update(JSON.stringify(config)).digest('hex');
    res.setHeader('ETag', '"' + eTag + '"');
    res.setHeader('Content-Type', 'application/json');
    res.setHeader('Cache-Control', 'public, max-age=31557600');
});

Testet with chrom(42.x) and firefox(37.x)

Thx for response.

4
  • Yes you can cache JSON responses. At first glance it seems like a browser side issue. You shouldn't be sending pragma: no-cache in the request headers unless you disabled cache in chrome debugger tools or elsewhere in your browser settings. How are you issuing this request? Commented May 13, 2015 at 17:27
  • I just call the api route, using the browser url bar. I also tried to call the route using a script tag like <script src="localhost:3000/api/config"></script> returning a javascript object var config = {...}. Commented May 14, 2015 at 15:53
  • I read that it should be possible with an ajax request but i need a direct call. Commented May 14, 2015 at 15:59
  • I found a hint, i used res.end() to send response maybe thats the problem, i will try that again on monday. Commented May 14, 2015 at 19:22

3 Answers 3

1

Hi this code seems to work for me:

router.get('/config', function(req, res) {
    var eTag = crypto.createHash('md5').update(JSON.stringify(config)).digest('hex');

    if (req.headers['if-none-match'] && req.headers['if-none-match'] === '"' + eTag + '"') {
        res.status(304);
        res.end();
    } else {
        res.setHeader('ETag', '"' + eTag + '"');
        res.setHeader('Content-Type', 'application/json');
        res.setHeader('Cache-Control', 'public, max-age=31557600');
        res.send(JSON.stringify(config));
    }
});

Calling the api using browser url bar http://localhost:3000/api/config

Sign up to request clarification or add additional context in comments.

3 Comments

you must be using an older version of express? express handles etags for you by default in more recent versions. You shouldn't need that if-block. See here: expressjs.com/4x/api.html#app.set.
Using express 4, I get the 304 header, and the content type and the etag, back with just: router.get( '/config', function( req, res ) { res.send( config ); } );
Yes you are absolutely right. I did figured it out by myself. I'm not aware why it doesn't worked at the beginning.
0

Looks like you might be using chrome. Chrome should include the following header in the request after "f5":

If-None-Match:"94d52736bcd99b1ac771f13b1bbdf622"

If you don't see this, check the chrome settings / General and make sure that "Disable cache (while DevTools is open) is not checked:

Disable cache not checked in Chrome dev tools

5 Comments

Disable cache (while DevTools is open) is not checked.
@LukasBonzelett what library are you using to call the API? JQuery?
I do a direct call its no ajax call.
You call the API by typing a URL into a browser?
Yes, or i call it within a script tag as resource. The Api request returns a javascript object.
0

Using jQuery we can use the ifModified option:

$.ajax({
   type: "GET",
   ifModified: true,
   url: "http://localhost:3000/api/config"
}).then(function(data) {
   . . .
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.