forked from JavaScriptSolidServer/JavaScriptSolidServer
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvary-cache-headers.test.js
More file actions
114 lines (106 loc) · 4.77 KB
/
vary-cache-headers.test.js
File metadata and controls
114 lines (106 loc) · 4.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/**
* Regression tests for #315 — inconsistent Vary / Cache-Control across
* conneg variants caused stale-render races on browser reload.
*
* What we guarantee now:
* - Every variant of the same URL returns an *identical* Vary header.
* - RDF data variants carry Cache-Control that forces revalidation via
* ETag, so a cached body cannot silently serve across auth changes or
* be picked up on a top-level navigation by mistake.
* - The mashlib HTML wrapper keeps `no-store` (it's a bootstrap template).
*/
import { describe, it, before, after } from 'node:test';
import assert from 'node:assert';
import {
startTestServer,
stopTestServer,
request,
createTestPod
} from './helpers.js';
describe('Vary / Cache-Control consistency (#315)', () => {
before(async () => {
await startTestServer({ conneg: true, mashlibCdn: true });
await createTestPod('varytest');
// Create a JSON-LD resource to exercise all variants.
await request('/varytest/public/card.jsonld', {
method: 'PUT',
headers: { 'Content-Type': 'application/ld+json' },
body: JSON.stringify({
'@context': { foaf: 'http://xmlns.com/foaf/0.1/' },
'@id': '#me',
'foaf:name': 'Vary Test'
}),
auth: 'varytest'
});
});
after(async () => { await stopTestServer(); });
it('Vary header is identical across all conneg variants of the same URL', async () => {
const accepts = [
'text/html,*/*;q=0.8', // mashlib HTML wrapper
'text/turtle', // Turtle conversion
'application/ld+json' // native JSON-LD
];
const varyValues = [];
for (const accept of accepts) {
const res = await request('/varytest/public/card.jsonld', { headers: { Accept: accept } });
varyValues.push({ accept, vary: res.headers.get('vary') });
}
// All three variants must carry the same Vary — inconsistent Vary is
// what confused browser caches into serving the wrong variant.
const uniqueVaryValues = new Set(varyValues.map((v) => v.vary));
assert.strictEqual(uniqueVaryValues.size, 1,
`expected identical Vary across variants, got: ${JSON.stringify(varyValues)}`);
const vary = [...uniqueVaryValues][0];
assert.ok(vary, `expected Vary header across variants, got: ${JSON.stringify(varyValues)}`);
assert.match(vary, /Accept/, 'Vary must include Accept (conneg active)');
assert.match(vary, /Authorization/, 'Vary must include Authorization (WAC)');
assert.match(vary, /Origin/, 'Vary must include Origin (CORS)');
});
it('mashlib HTML wrapper uses Cache-Control: no-store', async () => {
const res = await request('/varytest/public/card.jsonld', {
headers: { Accept: 'text/html,*/*;q=0.8' }
});
assert.match(res.headers.get('content-type') || '', /text\/html/);
assert.strictEqual(res.headers.get('cache-control'), 'no-store');
});
it('RDF data variants force revalidation (no stale bodies across auth changes)', async () => {
// Full expected policy — pinning every directive so a regression that
// drops `private` or `must-revalidate` (both needed to prevent auth-state
// leakage and force freshness) fails the test.
const expected = 'private, no-cache, must-revalidate';
for (const accept of ['text/turtle', 'application/ld+json']) {
const res = await request('/varytest/public/card.jsonld', { headers: { Accept: accept } });
assert.strictEqual(res.headers.get('cache-control'), expected,
`Cache-Control mismatch on Accept: ${accept}`);
// ETag is preserved so revalidation is cheap (304).
assert.ok(res.headers.get('etag'), `expected ETag on ${accept} variant`);
}
});
it('container index.html data-island variants also carry revalidating Cache-Control', async () => {
// Publish an index.html with a JSON-LD data island; conneg should extract
// and serve it as Turtle/JSON-LD. Those variants were missing
// Cache-Control pre-#315.
const html = [
'<!doctype html><html><head>',
'<script type="application/ld+json">',
JSON.stringify({
'@context': { foaf: 'http://xmlns.com/foaf/0.1/' },
'@id': '#this',
'foaf:name': 'Island'
}),
'</script></head><body>hi</body></html>'
].join('');
await request('/varytest/public/index.html', {
method: 'PUT',
headers: { 'Content-Type': 'text/html' },
body: html,
auth: 'varytest'
});
const expected = 'private, no-cache, must-revalidate';
for (const accept of ['text/turtle', 'application/ld+json']) {
const res = await request('/varytest/public/', { headers: { Accept: accept } });
assert.strictEqual(res.headers.get('cache-control'), expected,
`Cache-Control mismatch on island variant (Accept: ${accept})`);
}
});
});