Public API: cache headers for a CDN
The public read answers of OpenCatalogi can be kept by a CDN or a browser. A visitor without an account then gets a cached answer, and Nextcloud answers fewer requests.
Which answers
GET /api/{catalogSlug}: the publications of a catalogueGET /api/{catalogSlug}/{id}: one publicationGET /api/{catalogSlug}/{id}/attachments: its attachmentsGET /api/search: the public search
What the headers say
| caller | answer | headers |
|---|---|---|
| no account | 200 | Cache-Control: public, max-age=N, must-revalidate, a weak ETag over the answer, Vary: Origin, Accept, Accept-Language |
no account, If-None-Match matches | 304, no body | the same ETag and Cache-Control |
| signed in | any | Cache-Control: private, no-store, no ETag |
| anyone | an error (4xx, 5xx) | no public cache header |
| no account, the request carries a body, cache time above 0 | 200 | Cache-Control: no-store, no ETag |
A signed-in answer can hold records the public cannot read, so it is never cached. The ETag is computed over the answer after the access check, so it does not reveal that a hidden record changed.
Set the cache time
Open Administration settings → OpenCatalogi → Publishing options and set Public cache time (seconds). The default is 60, the highest value is 3600 (one hour). Set 0 to switch the public cache headers off; the answers then go out as before.
The same value is the app config key public_api_cache_seconds:
occ config:app:set opencatalogi public_api_cache_seconds --value=300
Setting up a CDN
- Let the CDN respect
Cache-ControlandETagfrom the origin. It should revalidate withIf-None-Matchoncemax-agehas passed. - Keep
Origin,AcceptandAccept-Languagein the cache key. The answers carryVary: Origin, Accept, Accept-Languagebecause the CORS header, the format (a publication answers JSON, or schema.org JSON-LD forAccept: application/ld+json) and the language differ per site and per reader. A CDN that ignoresVary: Origincan hand one site's CORS answer to another site. - Do not cache requests that carry a Nextcloud session cookie or an
Authorizationheader. The origin already marks those answersprivate, no-store. - Bypass the cache for those requests as well: do not serve them from it either. A cached anonymous answer for the same URL would otherwise reach a signed-in editor, without concept or future-dated publications.
- Views served from the CDN are not counted in the publication statistics. Only a request that reaches Nextcloud and gets a full answer counts as a view; a revalidation answered with 304 does not.
The withdrawal delay
A withdrawn or changed publication can stay visible in a cached answer for up to the cache time. With the default of 60 seconds that is one minute. Choose a shorter time if a withdrawal must disappear sooner, or purge the CDN by URL after a withdrawal. A purge does not reach the browsers of visitors who already received the answer: they keep it until its max-age has passed.