Opened 3 years ago

Closed 3 years ago

#21050 closed defect (wontfix)

Onionoo serves invalid cache headers

Reported by: lukechilds Owned by: metrics-team
Priority: Medium Milestone:
Component: Metrics/Onionoo Version:
Severity: Normal Keywords:
Cc: Actual Points:
Parent ID: Points:
Reviewer: Sponsor:

Description

Onionoo serves invalid cache headers the first time you receive a 304. All 304 responses after that are ok until the cache max-age is reached. Then the next 304 response will have invalid headers and after that it's ok again until the new max-age is reached etc.

They are invalid because the Date header isn't reset once the max-age is reached and the Age header carries on incrementing. This results in an age that is higher than the max-age, which means the headers are saying the content has already expired before it's been sent.

Example:


Make a request at 09:10:32

Response code: 200
Date: Wed, 21 Dec 2016 09:10:32 GMT
Age: 0
Cache-Control: public, max-age=300
Last-Modified: Wed, 21 Dec 2016 08:23:36 GMT

AKA This content is from 09:10:32 (now) and you can cache it until 09:15:32 (5 minutes)


Now lets make a request at 09:15:41, it's been more than 5 minutes so we'll set the If-Modified-Since header to see if our cached version is still up to date

Response code: 304
Date: Wed, 21 Dec 2016 09:10:32 GMT
Age: 309
Cache-Control: public, max-age=300
Last-Modified: Wed, 21 Dec 2016 08:23:36 GMT

AKA This content is from 09:15:41 (now) and you can cache it until 09:15:32 (9 seconds ago).

So the headers are saying it was out of date 9 seconds before the response was sent. It wasn't, it's still fresh, it's just the Date header wasn't updated so the max-age was calculated from an old date.


If we make another request with If-Modified-Since set at 09:15:54 (13 seconds later) everything catches up:

Response code: 304
Date: Wed, 21 Dec 2016 09:15:41 GMT
Age: 13
Cache-Control: public, max-age=300
Last-Modified: Wed, 21 Dec 2016 08:23:36 GMT

AKA This content is from 09:15:54 (now) and you can cache it until 09:20:41 (4:47 minutes)

Notice how the Date header is now correctly set as the date of our previous request with the age header calculated from that.


This is technically not abiding by the HTTP protocol:

https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

14.9 Cache-Control

The Cache-Control general-header field is used to specify directives that MUST be obeyed by all caching mechanisms along the request/response chain.

In the second request in the example above the max-age in the Cache-Control headers is 300 and the age is 309 which means that Onionoos caching mechanism isn't obeying the Cache-Control header.

The end result of this is that the first time a 304 response is sent it will never be cached by a client even though the content is still fresh. In the above example 3 HTTP requests needed to be made, if the headers were set correctly only 2 requests would have been required. Fixing this should reduce the amount of traffic that hits the Onionoo server.

Child Tickets

Change History (2)

comment:1 Changed 3 years ago by lukechilds

Sorry, where I said

the Date header wasn't updated so the max-age was calculated from an old date.

I meant age not max-age

comment:2 Changed 3 years ago by karsten

Resolution: wontfix
Status: newclosed

I was able to reproduce this issue: I got responses with max-age=2400 and an Age going up from 0 to 2405 depending on when I made the request. After that last response I got a new response with Age starting at 0 again.

But unless this breaks clients somehow, which I assume is not the case, I don't think this is worth investigating. We only run into this case at most once every 5 minutes per requested resource and for all clients requesting that resource. It's cheaper to provide more caching resources than hunt down and fix this bug. It's not even clear that this is a bug in the Java part of Onionoo or in the specific Varnish configuration used here. It might be a Varnish bug. But who knows.

I'm closing this ticket. Feel free to re-open this ticket if this issue breaks clients. And thanks for reporting anyway!

Note: See TracTickets for help on using tickets.