Etag not changing #1560

mangvlad opened this Issue Mar 28, 2013 · 10 comments


None yet
3 participants

I am serving some dynamic content (data API).
The operation (GET) supports returning content in two different formats (content types).

First request is issued with "Accept: application/x-type1" and in the response an Etag header is present/generated.

In the second response, the client (browser) is setting "Accept:application/x-type2" and not changing any other parameters, but "If-None-Match" is automatically included.

My express application returns 304 for the second request ignoring client's change to the Accept.



tj commented Mar 28, 2013

the etag is generated based on the actual content, it should be a weak etag technically but it's not right now but you can see that it's based on the response body here:

I am not sure I can follow this...
After the first request, the etag is generated, but when the second request comes, shouldn't it always send the request to my request handler since it is not static?

It seems that the browser if response had an etag will always send it back for the same url/query string even when one of the headers is different, so the solution should be on the server: for dynamic content etag should not be included/populated in the response...


tj commented Apr 10, 2013

are you using a reverse proxy cache at all? otherwise yeah it should do a conditional-get

I have node/express app running on my local host and I access it from the browser (no proxies).
I have a get handler that returns a list of objects (json) from DB. The list is long, so the size of the body is bigger than 1024 and etag is getting generated for it.

If I add new DB records or change my http header to return the same list in html, browser or my Javascript app will continue using the same etag and express will continue returning cached data, instead of what I need it to be.

The only way to fix it at the moment is to restart node or to keep adding "fake" query string parameters to be different every time, but both solutions are not acceptable for any "real" use...

I think there should be a way to disable etag (maybe for some of the handlers, so it still works as is for static content) or to access it from my request handler to decide if cache is ok to be used...


tj commented Apr 11, 2013

I have definitely not seen this behaviour, the ETag should not at all be the same for different content, not sure what to think about that

I think I got it: I was confusing Etag with actual cache...

After looking at this further, I now understand that all Etag does for me is changing the response code to 304 instead of 200, but the response body is still there and is generated by my code. The caller, on the other hand getting 304 may choose to ignore the body...

The root cause of my problem seems to be on the client (in this case Swagger UI) and its logic for when certain headers (namely Accept) are send/modified.

It probably still be useful to be able to disable Etag logic globally so 304 is not used, but this is not as critical...


tj commented Apr 25, 2013

304 isn't harmful at all, with XHR the browser just gives you 200 for 304s since it's already in cache

Yes, but when express is used to expose an API, it will be used not just by browsers, so getting a status that was not expected may be not a desired behavior...


tj commented Apr 26, 2013

well if the API client is sending If-None-Match then it obviously knows how to negotiate caches, thus it's not a problem, otherwise it wouldn't send those request header fields

Good point! Maybe it is just a matter of training/documentation for the API but also for express to have this explained somewhere.

Thanks for your help!

jonathanong closed this Sep 7, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment