The Http caching filter for jakarta servlet applications is a library which aim to enable http caching for jakarta servlet applications according to http caching information provided by an openAPI specification.
Simple steps for getting started with a classical jakarta servlet application.
- Add to dependencies
Write a openAPI specification file in the src/main/resources
of your project with x-cache
extensions inside responses code.
Now, if you run the application, you can verify that the annotated endpoints serve cache headers with resources.
How to write tests to verify that required cache headers are available
The main principle of http cache is that a web client can save data exchange over the network if a resource it needs has not changed since the last time it got it from the server :
- client can save a whole http request to get again a resource, while the stored resource is fresh, if the server gave a peremption date for the resource at the first request : this can be done using
cache-control
header - client can save data exchange to get again a resource if the client received a hash for resource from the server and the server answers that the hash has not changed when the client requests again the resource : this can be done using
etag
andcache-control
headers - client can also save data exchange if it knows the resource has not been modified since it last got it : this can be done with headers
last-modified
...
API resources can also benefit http caching because, whereas they can be often modified, business rules can specify for few of them how long they can be stored and client can always asks servers if hash of resources changed, avoiding to send an other time the resource through the network in the same state. So http caching for API is relevant, in particular with etag
and cache-control
headers. Therefore, API servers should serve resources with this headers
A simple example explained
- cache-control directives for clients
- cache-control directives for server
- obsolete directives
WIP
- private attribute for
cache-control
directive - no-store attribute for
cache-control
directive
Client -> Browser memory cache (PRIVATE) -> Browser disk cache (PRIVATE) -> CDN (PUBLIC - SHARE) -> Reverse Proxy (PUBLIC - SHARE) -> Server
The server can put the header vary on its response to instruct the cache to store various exemplaries of a resource
vary
lists headers. The cache stores a different exemplary of the resource for each different value of each header of the vary
list.
For example, if the server responses the GET /user/10
with the vary: accept
header, caches will store :
- one exemplary for
GET /user/10, accept: application/json
- an other one exemplary for
GET /user/10, accept: application/xml
By this way, one can fill very quickly public caches
- https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-caching.html#mvc-caching-cachecontrol
- https://docs.spring.io/spring-framework/reference/web/webmvc/filters.html#filters-shallow-etag
- https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#fixed-fields-15
- https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#header-object
- OAI/OpenAPI-Specification#2784
- Hhttp fileds (headers)
- RFC 9111 about http caching
- RFC 9110 : etag
- [DEVFEST Lille 2023] - #RetourAuxSources : Le cache HTTP - Hubert Sablonnière 🇫🇷
- https://blog.payara.fish/caching-rest-resources-in-jakarta-rest-formerly-jax-rs