From edf4015d6a483c23063793d7eac1a246dff20f4d Mon Sep 17 00:00:00 2001 From: Neil Hanlon Date: Mon, 26 Feb 2024 23:09:37 -0500 Subject: [PATCH] allow custom cache control settings for requests Currently, the publisher server only allows for three options when setting cache-control settings: extended (one year), never (no-store), and null, which skips setting the cache-control header. At the same time, the implementation for serving local content prevents mutation of the backend response after receiving it (e.g., to add a custom cache-control header based on a path), as the act of catching the response to modify it strips the original Response headers. This is contrary to the documentation[1] which indicates the headers can be mutated in this fashion. (i.e., by passing beresp.body through `pipeThrough`) with a transform stream. From my testing, it's not possible to mutate the headers along with (or without) the content. This change modifies the serveRequest method to add an optional cache parameter which allows the user to set a custom cache-control string. Although there are other ways to solve this (such as allowing serveRequest to accept arbitrary headers which will be appended/merged, or figuring out if the broken example is the result of a bug or old documentation), this method solves my current needs. [1] https://www.fastly.com/documentation/guides/compute/javascript/#parsing-and-transforming-responses Signed-off-by: Neil Hanlon --- src/server/publisher-server.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/server/publisher-server.ts b/src/server/publisher-server.ts index e924d35..caae926 100644 --- a/src/server/publisher-server.ts +++ b/src/server/publisher-server.ts @@ -27,7 +27,7 @@ function requestAcceptsTextHtml(req: Request) { type AssetInit = { status?: number, headers?: Record, - cache?: 'extended' | 'never' | null, + cache?: 'extended' | 'never' | null | string, }; export class PublisherServer { @@ -238,6 +238,8 @@ export class PublisherServer { case 'never': cacheControlValue = 'no-store'; break; + default: + cacheControlValue = init.cache; } headers['Cache-Control'] = cacheControlValue; } @@ -264,7 +266,7 @@ export class PublisherServer { }); } - async serveRequest(request: Request): Promise { + async serveRequest(request: Request, cache: string): Promise { // Only handle GET and HEAD if (request.method !== 'GET' && request.method !== 'HEAD') { @@ -274,10 +276,12 @@ export class PublisherServer { const url = new URL(request.url); const pathname = url.pathname; + const doCache = cache || (this.testExtendedCache(pathname) ? 'extended' : null); + const asset = this.getMatchingAsset(pathname); if (asset != null) { return this.serveAsset(request, asset, { - cache: this.testExtendedCache(pathname) ? 'extended' : null, + cache: doCache, }); }