Skip to content

Commit 15b9a1b

Browse files
authored
chore: enable cache-control header conformance tests (#943)
Send header via fetch request in tests
1 parent 87dbae8 commit 15b9a1b

File tree

5 files changed

+104
-12
lines changed

5 files changed

+104
-12
lines changed

src/sw/handlers/content-request-handler.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,12 @@ function shouldCacheResponse (response: Response, args: FetchHandlerArg): boolea
108108
const log = getSwLogger('should-cache-response')
109109

110110
if (!response.ok) {
111-
log.trace('response not ok, not caching %o', response)
111+
log.trace('response not ok, not caching %s %d %s', response.url, response.status, response.statusText)
112+
113+
for (const [key, value] of response.headers) {
114+
log.trace('%s: %s', key, value)
115+
}
116+
112117
return false
113118
}
114119

test-conformance/conformance.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,14 @@ test.describe('@helia/service-worker-gateway - gateway conformance', () => {
142142
const HEADERS = [
143143
'accept',
144144
'range',
145-
'if-none-match'
145+
'if-none-match',
146+
'cache-control'
146147
]
147148

148149
if ([...Object.keys(req.headers)].some(key => HEADERS.includes(key))) {
149150
response = await makeFetchRequest(page, url, {
150-
headers: new Headers(incomingHeadersToObject(req.headers))
151+
headers: new Headers(incomingHeadersToObject(req.headers)),
152+
redirect: 'follow'
151153
})
152154
} else {
153155
response = await loadWithServiceWorker(page, url.toString(), {

test-conformance/fixtures/expected-passing-tests.json

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,8 @@
264264
"TestNativeDag/HEAD_plain_JSON_codec_with_an_explicit_DAG-JSON_format_returns_HTTP_200/Header_Etag",
265265
"TestNativeDag/HEAD_plain_JSON_codec_with_an_explicit_DAG-JSON_format_returns_HTTP_200/Header_Content-Type",
266266
"TestNativeDag/HEAD_plain_JSON_codec_with_an_explicit_DAG-JSON_format_returns_HTTP_200/Header_Content-Length",
267+
"TestNativeDag/HEAD_plain_JSON_codec_with_only-if-cached_for_missing_block_returns_HTTP_412_Precondition_Failed",
268+
"TestNativeDag/HEAD_plain_JSON_codec_with_only-if-cached_for_missing_block_returns_HTTP_412_Precondition_Failed/Status_code",
267269
"TestNativeDag/GET_plain_JSON_codec_on_%2Fipfs_with_Accept:_text%2Fhtml_returns_HTML_%28dag-index-html%29",
268270
"TestNativeDag/GET_plain_JSON_codec_on_%2Fipfs_with_Accept:_text%2Fhtml_returns_HTML_%28dag-index-html%29/Check_0",
269271
"TestNativeDag/GET_plain_JSON_codec_on_%2Fipfs_with_Accept:_text%2Fhtml_returns_HTML_%28dag-index-html%29/Check_0/Status_code",
@@ -314,6 +316,8 @@
314316
"TestNativeDag/HEAD_plain_CBOR_codec_with_an_explicit_DAG-JSON_format_returns_HTTP_200/Header_Etag",
315317
"TestNativeDag/HEAD_plain_CBOR_codec_with_an_explicit_DAG-JSON_format_returns_HTTP_200/Header_Content-Type",
316318
"TestNativeDag/HEAD_plain_CBOR_codec_with_an_explicit_DAG-JSON_format_returns_HTTP_200/Header_Content-Length",
319+
"TestNativeDag/HEAD_plain_CBOR_codec_with_only-if-cached_for_missing_block_returns_HTTP_412_Precondition_Failed",
320+
"TestNativeDag/HEAD_plain_CBOR_codec_with_only-if-cached_for_missing_block_returns_HTTP_412_Precondition_Failed/Status_code",
317321
"TestNativeDag/GET_plain_CBOR_codec_on_%2Fipfs_with_Accept:_text%2Fhtml_returns_HTML_%28dag-index-html%29",
318322
"TestNativeDag/GET_plain_CBOR_codec_on_%2Fipfs_with_Accept:_text%2Fhtml_returns_HTML_%28dag-index-html%29/Check_0",
319323
"TestNativeDag/GET_plain_CBOR_codec_on_%2Fipfs_with_Accept:_text%2Fhtml_returns_HTML_%28dag-index-html%29/Check_0/Status_code",
@@ -443,10 +447,10 @@
443447
"TestGatewayCache/GET_for_%2Fipfs%2F_unixfs_dir_as_JSON_succeeds",
444448
"TestGatewayCache/GET_for_%2Fipfs%2F_unixfs_dir_as_JSON_succeeds/Status_code",
445449
"TestGatewayCache/GET_for_%2Fipfs%2F_unixfs_dir_as_JSON_succeeds/Header_Cache-Control",
446-
"TestGatewayCache/HEAD_for_%2Fipfs%2F_with_only-if-cached_succeeds_when_in_local_datastore",
447-
"TestGatewayCache/HEAD_for_%2Fipfs%2F_with_only-if-cached_succeeds_when_in_local_datastore/Status_code",
448-
"TestGatewayCache/GET_for_%2Fipfs%2F_with_only-if-cached_succeeds_when_in_local_datastore",
449-
"TestGatewayCache/GET_for_%2Fipfs%2F_with_only-if-cached_succeeds_when_in_local_datastore/Status_code",
450+
"TestGatewayCache/HEAD_for_%2Fipfs%2F_with_only-if-cached_fails_when_not_in_local_datastore",
451+
"TestGatewayCache/HEAD_for_%2Fipfs%2F_with_only-if-cached_fails_when_not_in_local_datastore/Status_code",
452+
"TestGatewayCache/GET_for_%2Fipfs%2F_with_only-if-cached_fails_when_not_in_local_datastore",
453+
"TestGatewayCache/GET_for_%2Fipfs%2F_with_only-if-cached_fails_when_not_in_local_datastore/Status_code",
450454
"TestGatewayCacheWithIPNS",
451455
"TestGatewayCacheWithIPNS/GET_for_%2Fipns%2F_unixfs_dir_as_DAG-JSON_succeeds",
452456
"TestGatewayCacheWithIPNS/GET_for_%2Fipns%2F_unixfs_dir_as_DAG-JSON_succeeds/Check_0",

test-conformance/fixtures/get-wontfix-tests.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,11 @@ export function getWontFixTests (): string[] {
2424
'TestPathing/GET_DAG-JSON_traversal_returns_501_if_there_is_path_remainder',
2525
'TestPathing/GET_DAG-CBOR_traversal_returns_501_if_there_is_path_remainder',
2626

27-
// we cannot send a cache-control header
27+
// these tests require the block /ipfs/bafybeib3ffl2teiqdncv3mkz4r23b5ctrwkzrrhctdbne6iboayxuxk5ui/root2/root3/root4
28+
// to be in the blockstore already
2829
'TestNativeDag/Cache_control_HTTP_headers_%28json%29',
29-
'TestNativeDag/HEAD_plain_JSON_codec_with_only-if-cached_for_missing_block_returns_HTTP_412_Precondition_Failed',
30-
'TestNativeDag/HEAD_plain_CBOR_codec_with_only-if-cached_for_missing_block_returns_HTTP_412_Precondition_Failed',
31-
'TestGatewayCache/HEAD_for_%2Fipfs%2F_with_only-if-cached_fails_when_not_in_local_datastore',
32-
'TestGatewayCache/GET_for_%2Fipfs%2F_with_only-if-cached_fails_when_not_in_local_datastore',
30+
'TestGatewayCache/HEAD_for_%2Fipfs%2F_with_only-if-cached_succeeds_when_in_local_datastore',
31+
'TestGatewayCache/GET_for_%2Fipfs%2F_with_only-if-cached_succeeds_when_in_local_datastore',
3332

3433
// we cannot send if-none-match header
3534
'TestGatewayCache/GET_for_%2Fipfs%2F_file_with_matching_Etag_in_If-None-Match_returns_304_Not_Modified',

test-e2e/cache-control.spec.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import { stop } from '@libp2p/interface'
2+
import * as cbor from 'cborg'
3+
import { createKuboRPCClient } from 'kubo-rpc-client'
4+
import { testPathRouting as test, expect } from './fixtures/config-test-fixtures.js'
5+
import { makeFetchRequest } from './fixtures/make-range-request.ts'
6+
import { setConfig } from './fixtures/set-sw-config.ts'
7+
import { waitForServiceWorker } from './fixtures/wait-for-service-worker.ts'
8+
import type { KuboRPCClient } from 'kubo-rpc-client'
9+
import type { CID } from 'multiformats/cid'
10+
11+
const object = {
12+
hello: 'world'
13+
}
14+
15+
test.describe('cache-control', () => {
16+
let kubo: KuboRPCClient
17+
let cid: CID
18+
let block: Uint8Array
19+
20+
test.beforeEach(async ({ page }) => {
21+
if (process.env.KUBO_GATEWAY == null || process.env.KUBO_GATEWAY === '') {
22+
throw new Error('KUBO_GATEWAY not set')
23+
}
24+
25+
kubo = createKuboRPCClient(process.env.KUBO_RPC)
26+
27+
block = cbor.encode(object)
28+
cid = await kubo.block.put(block, {
29+
format: 'cbor'
30+
})
31+
32+
await waitForServiceWorker(page)
33+
await setConfig(page, {
34+
gateways: [
35+
process.env.KUBO_GATEWAY
36+
],
37+
routers: [
38+
process.env.KUBO_GATEWAY
39+
],
40+
acceptOriginIsolationWarning: true,
41+
renderHTMLViews: false
42+
})
43+
})
44+
45+
test.afterEach(async () => {
46+
await stop(kubo)
47+
})
48+
49+
test('should return block that is in local datastore', async ({ page }) => {
50+
// try offline without block
51+
const response0 = await makeFetchRequest(page, `/ipfs/${cid}`, {
52+
headers: {
53+
'cache-control': 'only-if-cached'
54+
}
55+
})
56+
expect(response0.status()).toBe(412)
57+
58+
// fetch block from gateway
59+
const response1 = await makeFetchRequest(page, `/ipfs/${cid}`)
60+
expect(response1.status()).toBe(200)
61+
expect(new Uint8Array(await response1.body())).toStrictEqual(block)
62+
63+
// try again offline, should be cached now
64+
const response2 = await makeFetchRequest(page, `/ipfs/${cid}`, {
65+
headers: {
66+
'cache-control': 'only-if-cached'
67+
}
68+
})
69+
70+
expect(response2.status()).toBe(200)
71+
expect(new Uint8Array(await response2.body())).toStrictEqual(block)
72+
})
73+
74+
test('should return 412 for block that is not in local datastore', async ({ page }) => {
75+
const response = await makeFetchRequest(page, '/ipfs/bafybeicvjyaiqmgfe7wupl72gpf7cadwyjqf7nzsxrap6npgrgtd3d6m4a', {
76+
headers: {
77+
'cache-control': 'only-if-cached'
78+
}
79+
})
80+
expect(response.status()).toBe(412)
81+
})
82+
})

0 commit comments

Comments
 (0)