Skip to content

Commit

Permalink
Frank/#165 fix (#166)
Browse files Browse the repository at this point in the history
* defined response status on cached responses. fixes 165

* updated mocks and added tests for range requests

* fixed range request test
  • Loading branch information
shagamemnon authored and GregBrimble committed Feb 8, 2024
1 parent 7284ef5 commit e848b44
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 8 deletions.
20 changes: 18 additions & 2 deletions packages/kv-asset-handler/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,24 @@ const getAssetFromKV = async (event: FetchEvent, options?: Partial<Options>): Pr
}
response = new Response(null, response)
} else {
response = new Response(response.body, response)
response.headers.set('cf-cache-status', 'HIT')
headers.set('CF-Cache-Status', 'HIT')
// fixes #165
let opts = {
headers,
status: 0,
statusText: ''
}
if (response.status) {
opts.status = response.status
opts.statusText = response.statusText
} else if (headers.has('Content-Range')) {
opts.status = 206
opts.statusText = 'Partial Content'
} else {
opts.status = 200
opts.statusText = 'OK'
}
response = new Response(response.body, opts)
}

} else {
Expand Down
38 changes: 32 additions & 6 deletions packages/kv-asset-handler/src/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,43 @@ export const mockCaches = () => {
url: key.url,
headers: {}
}
let response
if (key.headers.has('if-none-match')) {
let makeStrongEtag = key.headers.get('if-none-match').replace('W/', '')
Reflect.set(cacheKey.headers, 'etag', makeStrongEtag)
cacheKey.headers = {
'etag': key.headers.get('if-none-match')
}
response = cacheStore.get(JSON.stringify(cacheKey))
} else {
// if client doesn't send if-none-match, we need to iterate through these keys
// and just test the URL
const activeCacheKeys: Array<string> = Array.from(cacheStore.keys())
for (const cacheStoreKey of activeCacheKeys) {
if (JSON.parse(cacheStoreKey).url === key.url) {
response = cacheStore.get(cacheStoreKey)
}
}
}
if (response) {
// this appears overly verbose, but is necessary to document edge cache behavior
// The Range request header triggers the response header Content-Range ...
const range = key.headers.get('range')
if (range) {
response.headers.set('content-range', `bytes ${range.split('=').pop()}/${response.headers.get('content-length')}`)
}
// ... which we are using in this repository to set status 206
if (response.headers.has('content-range')) {
response.status = 206
} else {
response.status = 200
}
}
return cacheStore.get(JSON.stringify(cacheKey))
return response
},
async put (key: any, val: Response) {
let headers = new Headers(val.headers)
let url = new URL(key.url)
let resWithBody = new Response(val.body, { headers, status: 200 })
let resNoBody = new Response(null, { headers, status: 304 })
let body = await val.text()
let resp = new Response(body, { headers })
headers.set('content-length', (body.length).toString())
let cacheKey: CacheKey = {
url: key.url,
headers: {
Expand Down
15 changes: 15 additions & 0 deletions packages/kv-asset-handler/src/test/getAssetFromKV.ts
Original file line number Diff line number Diff line change
Expand Up @@ -439,4 +439,19 @@ test('getAssetFromKV if-none-match not sent but resource in cache, should return
}
})

test('getAssetFromKV if range request submitted and resource in cache, request fulfilled', async t => {
const resourceKey = 'cache.html'
const event1 = getEvent(new Request(`https://blah.com/${resourceKey}`))
const event2 = getEvent(new Request(`https://blah.com/${resourceKey}`, { headers: { 'range': 'bytes=0-10'}}))
const res1 = await getAssetFromKV(event1, { cacheControl: { edgeTTL: 720 } })
await res1
await sleep(2)
const res2 = await getAssetFromKV(event2)
if (res2.headers.has('content-range')) {
t.is(res2.status, 206)
} else {
t.fail('Response was undefined')
}
})

test.todo('getAssetFromKV when body not empty, should invoke .cancel()')

0 comments on commit e848b44

Please sign in to comment.