@teamscala/service-boot 0.23.552 → 0.23.554
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"repository": "https://github.com/teamgbg/service-boot",
|
|
28
28
|
"sideEffects": false,
|
|
29
29
|
"type": "module",
|
|
30
|
-
"version": "0.23.
|
|
30
|
+
"version": "0.23.554",
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@orpc/openapi": "*",
|
|
33
33
|
"@orpc/server": "*",
|
|
@@ -310,4 +310,4 @@
|
|
|
310
310
|
"./ws-boot-self-test": "./src/ws-boot-self-test.ts",
|
|
311
311
|
"./ws-boot-self-test.ts": "./src/ws-boot-self-test.ts"
|
|
312
312
|
}
|
|
313
|
-
}
|
|
313
|
+
}
|
package/src/asset-proxy.ts
CHANGED
|
@@ -18,16 +18,31 @@ const CACHE_HEADERS = {
|
|
|
18
18
|
Vary: "Accept",
|
|
19
19
|
} as const;
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* A content-addressed asset URL that answers 404 is a race artifact — a page
|
|
23
|
+
* fetched moments before an asset set rotated, or a rebuild mid-write. The
|
|
24
|
+
* URL carries no meaning a cache may keep: a stale HTML will never become
|
|
25
|
+
* valid again, and Cloudflare's default edge TTL caches a header-less 404 for
|
|
26
|
+
* hours (measured 2026-10-23: chunk 404s served `max-age=14400` from the edge
|
|
27
|
+
* for files that existed at origin), re-breaking every client that held the
|
|
28
|
+
* old page. Never cacheable.
|
|
29
|
+
*/
|
|
30
|
+
const NOT_FOUND_HEADERS = { "cache-control": "no-store" } as const;
|
|
31
|
+
|
|
32
|
+
export function assetNotFoundResponse(): Response {
|
|
33
|
+
return new Response("Not Found", { status: 404, headers: NOT_FOUND_HEADERS });
|
|
34
|
+
}
|
|
35
|
+
|
|
21
36
|
export async function handleAssetProxy(req: Request): Promise<Response> {
|
|
22
37
|
const url = new URL(req.url);
|
|
23
38
|
const prefix = "/api/assets/";
|
|
24
39
|
if (!url.pathname.startsWith(prefix)) {
|
|
25
|
-
return
|
|
40
|
+
return assetNotFoundResponse();
|
|
26
41
|
}
|
|
27
42
|
|
|
28
43
|
const key = decodeURIComponent(url.pathname.slice(prefix.length));
|
|
29
44
|
if (!key) {
|
|
30
|
-
return
|
|
45
|
+
return assetNotFoundResponse();
|
|
31
46
|
}
|
|
32
47
|
|
|
33
48
|
const s3 = await getClient();
|
|
@@ -48,7 +63,7 @@ export async function handleAssetProxy(req: Request): Promise<Response> {
|
|
|
48
63
|
error: err,
|
|
49
64
|
key,
|
|
50
65
|
});
|
|
51
|
-
return
|
|
66
|
+
return assetNotFoundResponse();
|
|
52
67
|
}
|
|
53
68
|
|
|
54
69
|
const baseEtag = stats.etag || `"${key}"`;
|
|
@@ -95,7 +95,11 @@ export async function registerStaticAssets(
|
|
|
95
95
|
headers: { "cache-control": "public, max-age=31536000, immutable" },
|
|
96
96
|
});
|
|
97
97
|
}
|
|
98
|
-
|
|
98
|
+
// A hashed asset URL that misses is a race artifact (page from before an
|
|
99
|
+
// asset rotation, or a rebuild mid-write) — never cacheable, else the
|
|
100
|
+
// edge pins the 404 and re-breaks every client holding the old page
|
|
101
|
+
// (assetNotFoundResponse's header note).
|
|
102
|
+
return new Response("Not Found", { status: 404, headers: { "cache-control": "no-store" } });
|
|
99
103
|
});
|
|
100
104
|
|
|
101
105
|
app.get("/ext/*", async (c) => {
|
|
@@ -110,6 +114,6 @@ export async function registerStaticAssets(
|
|
|
110
114
|
headers: { "cache-control": "public, max-age=3600" },
|
|
111
115
|
});
|
|
112
116
|
}
|
|
113
|
-
return
|
|
117
|
+
return new Response("Not Found", { status: 404, headers: { "cache-control": "no-store" } });
|
|
114
118
|
});
|
|
115
119
|
}
|
|
@@ -87,7 +87,12 @@ export async function buildMinimalApp(
|
|
|
87
87
|
const logo = await resolveErrorPageLogo(serviceSlug);
|
|
88
88
|
return buildResourceNotFoundResponse("page", logo, 404);
|
|
89
89
|
}
|
|
90
|
-
|
|
90
|
+
// No-store: a 404 a cache may keep (Cloudflare's default edge TTL caches
|
|
91
|
+
// a header-less 404 on cacheable extensions for hours) re-serves the miss
|
|
92
|
+
// long after the resource exists — same class as the asset-route misses.
|
|
93
|
+
return c.json({ error: "Not Found" }, 404, {
|
|
94
|
+
"cache-control": "no-store",
|
|
95
|
+
});
|
|
91
96
|
});
|
|
92
97
|
|
|
93
98
|
app.use("*", readinessGate);
|