I try to constantly deepen my knowledge of HTTP and REST.
Recently, I stumbled upon the list of all registered HTTP Headers.
This post is dedicated to the Vary
HTTP Header.
The problem
Two years ago, I wrote about web resource caching server-side.
The idea is to set up a component between the client and the upstream to cache previously computed results to avoid overloading the latter.
Depending on your infrastructure and requirements, this component can be a reverse proxy or an API Gateway.
HTTP offers the Cache-Control header to customize the different aspects of caching, e.g., the time the server holds the resource in cache before it considers it stale.
I used plugin configuration in the above post, but you can also delegate to Cache-Control
.
Now, imagine the following scenario.
You request a resource, _e.g., GET /book/1
and get the result:
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": 1,
"title": "Notre-Dame de Paris"
}
The request succeeds; the result is cached.
Now, I request the same resource, but because my code works around XML, I set the Accept
header to application/xml
.
Unfortunately, the server returns the cached JSON resource, which differs from what I asked and probably utterly breaks my code.
The problem is that the cache key has a single dimension, the URL, by default.
The solution
We need a configurable multi-dimension cache key.
As you can probably guess by now, that’s the role of the Vary
header:
it explicitly lists all dimensions of the cache key.
In the example above, the upstream would communicate the additional cache key with the following:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Language: en
Vary: Accept
{
"id": 1,
"title": "Notre-Dame de Paris"
}
Instead of a single cache entry per URL, we now have one per MIME type/URL combination. Note that it’s up to the caching component to use this information.
Another common request header is Accept-Encoding
, which usually specifies which compression algorithms the client can accept.
Encoding is another possible cache key.
The specification allows specifying multiple cache keys:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Language: en
Vary: Accept, Accept-Encoding
{
"id": 1,
"title": "Notre-Dame de Paris"
}
Conclusion
I’ve described the Vary`response header in this post.
As soon as you configure caching, you must consider possible cache keys and use the `Vary
header accordingly.