Which Cache-Control header values are used by client/server? - http

I'm trying to understand which values for Cache-Control are to be used in the request and which are to be used in the response.
This is a good answer, but it doesn't mention if you should use those values in the response.
For example, should no-store be used in the request or the response?
Is no-cache only to be used in the request?
What would happen if it was used in the response instead of the request?
Is there any point in it being used in both the request and response?

It is indeed confusing that the same header name and directive can mean different things depending on whether it appears in a request or a response. This was acknowledged by one of the standard's editors, who wrote: "If we were designing Cache-Control from scratch today, we’d probably use a different name for the field in requests to help avoid this kind of confusion."
Fortunately, RFC 7234 describes Cache-Control request directives and response directives separately, so you can probably find the answers to your questions there. For example:
no-store can be used in either the request or the response. The meaning is basically the same, it's just a question of whether it's the client or the server who wants nothing to be stored.
no-cache can also be used in either the request or the response, but the meaning is different. If used in a request it means that the response to this request should not come from the cache (without validation). If used on a response, it means that future requests should not be satisfied with this response (without validation).

Related

Question about Etag and Cache-Control Header

I am trying to customize cache strategy.
because default setting is not fit on me ... Serviced by (Vercel).
I am unfamiliar with the cache setting through the http header, so I would like to ask for help.
Please check if my understanding is correct.
First of all, my response data doesn't change often.
But occasionally it changes.
Here is my plan.
Maybe i should revalidate every time. so i need to set my Cache-Control like this.
Cache-Control: public max-age=0 must-revalidate
I guess, with this way, my data will be stored in the client browser
and the browser will always send request that check the value is new.
And on the server, i'll write code to handle the things written in the lines below.
First, set Etag on response header.
Second, if the If-None-Match value comes from the request header, I compare it with my service logic to check whether the value is up to date.
If the If-None-Match value is up to date, I just write 304 in the response and send it.
And otherwise, I just respond with the data normally. with the new Etag value.

Are both "Cache request directives" and "Cache response directives" needed?

If I already have "Cache request directives," what is the point of "Cache response directives." Do they add anything? Will my application run the same without them?
I looking for proof whether "Cache response directives" are redundant. If they are redundant, I will not bother with them.
GC_
I assume you are asking as an application developer and if so, you should not bother with any Cache-Control header your application receives in a request.
Why?
Because that Cache-Control header is intended for caches before the request reaches your application.
It is not for your application.
This is explained in RFC7234 Section 5.2 (emphasis mine):
The "Cache-Control" header field is used to specify directives for caches along the request/response chain.
The purpose of the header is to tell caches what to do with the request.
Your application receives the header because it is attached to a request.
But just because you receive it, it doesn't mean it is for you.
Bottom line: ignore any Cache-Control header in a request.
Cache-Control in a response comes from your application and it is also intended for caches.
You use it to tell caches what to do with the response.
Basically, you use the header to specify whether the response is cacheable and if it is, for how long.
It is not merely a copy of the Cache-Control header received in a request.
Do they add anything?
Yes, they do.
Cache-Control in a response tells caches whether the response is cacheable and if it is,
it allows caches to serve an equivalent request immediately with a cached response.
This reduces your application's load and improves response times from a client's point of view.
RFC7234 Section 4.2 states:
When a response is "fresh" in the cache, it can be used to satisfy subsequent requests without contacting the origin server, thereby improving efficiency.
Your next question:
Will my application run the same without them?
It depends.
If your application doesn't add appropriate Cache-Control header for responses that must not be cached, future requests may receive stale responses.
So, I recommend that at the very least, add Cache-Control: no-cache to responses that must not be cached.
Additional explanation for your question in the comment section
The header should generally come from your backend, not your frontend.
This allows caches to accurately accelerates requests to your backend and keeps your frontend request code simple.
There is one exception: if the backend isn't yours and its response freshness policy doesn't match your requirement.
An example scenario may be in order:
Let's say, that in addition to sending requests to your own backend, your frontend also sends requests to someone else's backend.
This particular backend specifies that its responses are cacheable for at most 5 minutes, by either sending Cache-Control: max-age=300 or appropriate Expires header.
Let's also say, that you want the responses to be no more than 10 seconds stale, because 5 minutes is too stale for you.
Since the backend isn't yours, you can't change the 5-minutes directive, but you can send your requests with Cache-Control: max-age=10 thereby forcing the caches to fetch a fresh response if a cached response is older than 10 seconds, despite the 5-minutes directive from the backend.
That is the appropriate situation to send Cache-Control header from your frontend: the backend isn't yours and its response freshness policy doesn't match your requirement.
Are both "Cache request directives" and "Cache response directives" needed?
Yes. Cache-Control in request header and Cache-Control in response header are both needed. Even if you already have Cache-Control in request header, Cache-Control in response is not redundant. They are 2 different things. According to RFC7234:
cache directives are unidirectional in that the presence of a directive in a request does not imply that the same directive is to be given in the response.
Generally speaking, Cache-Control in response header controls the cache behaviour from resource provider's point of view. -- should the resource stored in cache? How long would it be valid? When requested, does it need to be revalidated? etc. As response headers can be configured for all HTTP requests, "Cache response directives" provides a way to define cache policy for all resources.
Cache-Control in request header, however, controls the cache behaviour from resource consumer's point of view. It's more like defining exceptional case where the cache policy of specific resource should be adjusted. If you check RFC7234, most of the "Request Cache-Control Directives" indicates that the client is willing to... or indicates that the client is unwilling to...
Also, as request headers can only be configured in some cases (e.g. Ajax), "Cache request directives" doesn't exist for many HTTP requests. For example, after HTML file is parsed, many HTTP requests will be created to fetch static resources (image files, css files etc.), there is no way to configure Cache-Control header for these requests manually in program.
If I already have "Cache request directives", what is the point of "Cache response directives"?
If you only have "Cache request directives" and never get Cache-Control response header, some problems will happen:
Without Cache-Control response header, the cache behaviour of all resources are decided by browser (e.g. calculate valid-time through LM-Factor algorithm). In the worst case, there would be no cache at all.
For static resources (e.g. image files, css files), as you can't configure Cache-Control in request, you lost cache control ability.

ETag with Accept-Language

I have a web service which puts an ETag on to each response so future calls can make use of the HTTP 304 (Not Modified) status. The ETag I generate really just a Base64 encoding of the query type along with the timestamp.
The problem I have is if the browser requests the same resource with a difference Accept-Language. The browser currently sends the same If-None-Match header, so the response is a 304, even thought the actual resource would have come back in a different language. So I thought the way to do this was to add a Vary Header, to specify to the client that the response varys with Accept & Accept-Language, as shown below.
Vary:Accept, Accept-Language
However my browser (Chrome) uses the same ETag regardless of the accept-language. What is the correct convention to use here?
Thanks
E-Tag identifies the response contents.
So better use a response body hash for E-Tag construction.
At least you can use hash of a query and a language concatenated.

Is absence of If-Match or If-Not-Match header shall be treated as unconditional request?

HTTP 1.1 spec has clear definition of server behavior if one of them is present. In my case, I have two clients, one old and one new. Old client ignores etag in response, and sends put request without etag; new client uses the If-Match + etag in put request. My understanding is that server shall take put request without If-Match as unconditional request and proceed. However, the consequence of it is that without etag, old client might do put request based on old data. So I have the question in Titie, "Is absence of If-Match or If-Not-Match header shall be treated as unconditional request?"
Well. A request is unconditional when it doesn't have any conditions attached to it. The base set of conditional request header fields is defines in http://greenbytes.de/tech/webdav/draft-ietf-httpbis-p4-conditional-25.html, extension specs such as WebDAV add more.
Whether the server actually accepts the unconditional request is another story, see http://greenbytes.de/tech/webdav/rfc6585.html#status-428.

HTTP Cache-Control: What is acceptable default behavior when it's not present?

I'm running into some HTTP caching issues, caused by some downstream apps not putting Cache-Control headers on time-sensitive data. I need to make the case that this is a broken situation.
Is there any succinct statement available online about permissible or common response-handling behaviors by caches and agents when the Cache-Control header is not present for HTTP 1.1? I see RFC2616, but it doesn't seem to include any normative or SHOULD statements about responses without a Cache-Control header.
I think when this directive is missing it is up to the browser to determine what it wants to do. (In this case your server may be the browser)
This is a pretty good write up of the way various browsers handled the issue:
http://www.f5.com/pdf/white-papers/browser-behavior-wp.pdf
Hope that helps.
There's no way to know what the proxies are doing or even which ones your customers are hitting, but if there's no Cache-Control header, they may well be sending a cached result. What you can do is add the header from the client-side (if thats an option), so the client would send the request for the resource with a header like this: Cache-Control:no-cache
More info on caching here:
https://developers.google.com/speed/docs/best-practices/caching#LeverageBrowserCaching
And here's a related stack-overflow question:
Why is Cache-Control attribute sent in request header (client to server)?
Hope it helps!

Resources