# Honoring ETag of cached content

**URL:** <https://www.ruby-forum.com/t/honoring-etag-of-cached-content/237267>\
**Category:** NGINX\
**Created:** [November 1, 2013, 10:29pm UTC](https://www.ruby-forum.com/t/honoring-etag-of-cached-content/237267 "2013-11-01T22:29:36Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![musicdenotation](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ea666f/32.png) [@musicdenotation](https://www.ruby-forum.com/u/musicdenotation)\
**Post date:** [November 1, 2013, 10:29pm UTC](https://www.ruby-forum.com/t/honoring-etag-of-cached-content/237267/1 "2013-11-01T22:29:36Z")

</div>

Hi,  
I’m using nginx proxy pass to cache content of our dynamic web  
application.

In order to save some bandwidth our client application uses conditional  
requests based on ETag. However nginx ignores the ETag of cached pages  
☹

What would be required if I want to honor the ETag of cached pages? Is  
something that can be achieve by means of configuration? or I would need  
to  
write an nginx module in C?

Thanks!

---

<div class="post-metadata">

**Author:** ![Marc\_Aymerich](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/8edcca/32.png) [@Marc\_Aymerich](https://www.ruby-forum.com/u/Marc_Aymerich)\
**Post date:** [November 2, 2013, 12:17am UTC](https://www.ruby-forum.com/t/honoring-etag-of-cached-content/237267/2 "2013-11-02T00:17:39Z")

</div>

Hello!

On Fri, Nov 01, 2013 at 10:29:06PM +0100, Marc Aymerich wrote:

> Hi,  
> I’m using nginx proxy pass to cache content of our dynamic web application.
> 
> In order to save some bandwidth our client application uses conditional  
> requests based on ETag. However nginx ignores the ETag of cached pages ☹
> 
> What would be required if I want to honor the ETag of cached pages? Is  
> something that can be achieve by means of configuration? or I would need to  
> write an nginx module in C?

It is expected to just work in 1.3.3+. If you don’t see it  
working, you may want to check the version you are running.

–  
Maxim D.  
[http://nginx.org/en/donation.html](http://nginx.org/en/donation.html)

---

<div class="post-metadata">

**Author:** ![Marc\_Aymerich](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/8edcca/32.png) [@Marc\_Aymerich](https://www.ruby-forum.com/u/Marc_Aymerich)\
**Post date:** [November 2, 2013, 2:55am UTC](https://www.ruby-forum.com/t/honoring-etag-of-cached-content/237267/3 "2013-11-02T02:55:57Z")

</div>

On Sat, Nov 2, 2013 at 12:16 AM, Maxim D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> > What would be required if I want to honor the ETag of cached pages? Is  
> > something that can be achieve by means of configuration? or I would need  
> > to  
> > write an nginx module in C?
> 
> It is expected to just work in 1.3.3+. If you don’t see it  
> working, you may want to check the version you are running.

Hi maxim,  
yeap I’m running 1.4.1 but I never get a 304 ☹  
This is what a response from cache looks like

# wget --no-check https://[fdf5:5351:1dfd:0:0:0:0:2]/api/ -S --header

‘If-None-Match: “83393a3900e4abce27212d7a27cae589”’ -q  
HTTP/1.1 200 OK  
Server: nginx/1.4.1  
Date: Sat, 02 Nov 2013 01:40:24 GMT  
Content-Type: application/json  
Transfer-Encoding: chunked  
Connection: keep-alive  
ETag: “83393a3900e4abce27212d7a27cae589”  
Allow: GET, HEAD, OPTIONS  
Vary: Accept, Cookie, Accept-Encoding  
Expires: Sat, 02 Nov 2013 01:41:24 GMT  
Cache-Control: max-age=60

This is my nginx config for this cached location

location /api/ {  
proxy\_pass [http://127.0.0.1:8080](http://127.0.0.1:8080);  
proxy\_redirect off;

```
proxy_ignore_headers Set-Cookie;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Protocol $scheme;

proxy_cache cache;
proxy_cache_key

```

$host$uri$is\_args$args$http\_accept\_encoding$http\_accept;  
proxy\_cache\_valid 1m;  
expires 1m;

```
set $skip_cache 0;
if ($request_method != GET) {
    set $skip_cache 1;
}
if ($http_cookie) {
   set $skip_cache 1;
}
if ($http_authorization) {
   set $skip_cache 1;
}
proxy_cache_bypass $skip_cache;

```

}

Maybe is there some conflicting configuration? I can not see it ☹ and  
ETags work just fine if I request to my backend server

# wget --no-check [http://127.0.0.1:8080/api/](http://127.0.0.1:8080/api/) -S --header 'If-None-Match:

“77e348fb6260a8dd90ca18c61f7cd472”’ -q  
HTTP/1.1 304 NOT MODIFIED  
Server: nginx/1.4.1  
Date: Sat, 02 Nov 2013 01:47:30 GMT  
Content-Length: 0  
Connection: keep-alive

Notice the etag value from cached content is different from the fresh  
one,  
even though the content is exactly the same, I presume this is nginx  
doing  
its job of updating the ETag for some differences because of caching,  
but  
still fails to reply a conditional request properly ☹

Thanks for your help!!

---

<div class="post-metadata">

**Author:** ![Marc\_Aymerich](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/8edcca/32.png) [@Marc\_Aymerich](https://www.ruby-forum.com/u/Marc_Aymerich)\
**Post date:** [November 2, 2013, 3:57pm UTC](https://www.ruby-forum.com/t/honoring-etag-of-cached-content/237267/4 "2013-11-02T15:57:29Z")

</div>

On Sat, Nov 2, 2013 at 1:10 PM, Maxim D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > >
> 
> Is
> 
> > yeap I’m running 1.4.1 but I never get a 304 ☹  
> > ETag: “83393a3900e4abce27212d7a27cae589”  
> > doing  
> > response. Meanwhile, you may add some Last-Modified to your  
> > backend responses as a workaround.

Wowo that’s it 🙂

# wget --no-check https://[fdf5:5351:1dfd:0:0:0:0:2]/api/ -S --header

‘If-None-Match: “83393a3900e4abce27212d7a27cae589”’ -q  
HTTP/1.1 304 Not Modified  
Server: nginx/1.4.1  
Date: Sat, 02 Nov 2013 14:53:29 GMT  
Connection: keep-alive  
Vary: Accept, Cookie, Accept-Encoding  
Last-Modified: Sat, 02 Nov 2013 14:53:29 GMT  
ETag: “83393a3900e4abce27212d7a27cae589”  
Allow: GET, HEAD, OPTIONS  
Expires: Sat, 02 Nov 2013 14:54:29 GMT  
Cache-Control: max-age=60

Thank you very much for your help maxim!

Shall I report this to nginx bug tracker?

---

<div class="post-metadata">

**Author:** ![Marc\_Aymerich](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/8edcca/32.png) [@Marc\_Aymerich](https://www.ruby-forum.com/u/Marc_Aymerich)\
**Post date:** [November 2, 2013, 1:11pm UTC](https://www.ruby-forum.com/t/honoring-etag-of-cached-content/237267/5 "2013-11-02T13:11:36Z")

</div>

Hello!

On Sat, Nov 02, 2013 at 02:55:09AM +0100, Marc Aymerich wrote:

> > > In order to save some bandwidth our client application uses conditional
> 
> Transfer-Encoding: chunked  
> Connection: keep-alive  
> ETag: “83393a3900e4abce27212d7a27cae589”  
> Allow: GET, HEAD, OPTIONS  
> Vary: Accept, Cookie, Accept-Encoding  
> Expires: Sat, 02 Nov 2013 01:41:24 GMT  
> Cache-Control: max-age=60

[…]

> Notice the etag value from cached content is different from the fresh one,  
> even though the content is exactly the same, I presume this is nginx doing  
> its job of updating the ETag for some differences because of caching, but  
> still fails to reply a conditional request properly ☹

Ok, I see what goes on here. Condintional requests (even ones  
using ETag in If-None-Match) are only handled by nginx if there is  
Last-Modified response date set, and it’s not set in your backend  
responses.

This needs to be addressed, If-None-Match / If-Match handling from  
cache shouldn’t require Last-Modified being present in a cached  
response. Meanwhile, you may add some Last-Modified to your  
backend responses as a workaround.

–  
Maxim D.  
[http://nginx.org/en/donation.html](http://nginx.org/en/donation.html)
