Spaces:
Configuration error
Configuration error
File size: 5,358 Bytes
5641073 |
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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
const makeServiceWorkerEnv = require('service-worker-mock')
const HASH = '123HASHBROWN'
export const getEvent = (request: Request): any => {
const waitUntil = async (callback: any) => {
await callback
}
return {
request,
waitUntil,
}
}
const store: any = {
'key1.123HASHBROWN.txt': 'val1',
'key1.123HASHBROWN.png': 'val1',
'index.123HASHBROWN.html': 'index.html',
'cache.123HASHBROWN.html': 'cache me if you can',
'测试.123HASHBROWN.html': 'My filename is non-ascii',
'%not-really-percent-encoded.123HASHBROWN.html': 'browser percent encoded',
'%2F.123HASHBROWN.html': 'user percent encoded',
'你好.123HASHBROWN.html': 'I shouldnt be served',
'%E4%BD%A0%E5%A5%BD.123HASHBROWN.html': 'Im important',
'nohash.txt': 'no hash but still got some result',
'sub/blah.123HASHBROWN.png': 'picturedis',
'sub/index.123HASHBROWN.html': 'picturedis',
'client.123HASHBROWN': 'important file',
'client.123HASHBROWN/index.html': 'Im here but serve my big bro above',
'image.123HASHBROWN.png': 'imagepng',
'image.123HASHBROWN.webp': 'imagewebp',
'你好/index.123HASHBROWN.html': 'My path is non-ascii',
}
export const mockKV = (store: any) => {
return {
get: (path: string) => store[path] || null,
}
}
export const mockManifest = () => {
return JSON.stringify({
'key1.txt': `key1.${HASH}.txt`,
'key1.png': `key1.${HASH}.png`,
'cache.html': `cache.${HASH}.html`,
'测试.html': `测试.${HASH}.html`,
'你好.html': `你好.${HASH}.html`,
'%not-really-percent-encoded.html': `%not-really-percent-encoded.${HASH}.html`,
'%2F.html': `%2F.${HASH}.html`,
'%E4%BD%A0%E5%A5%BD.html': `%E4%BD%A0%E5%A5%BD.${HASH}.html`,
'index.html': `index.${HASH}.html`,
'sub/blah.png': `sub/blah.${HASH}.png`,
'sub/index.html': `sub/index.${HASH}.html`,
client: `client.${HASH}`,
'client/index.html': `client.${HASH}`,
'image.png': `image.${HASH}.png`,
'image.webp': `image.${HASH}.webp`,
'你好/index.html': `你好/index.${HASH}.html`,
})
}
let cacheStore: any = new Map()
interface CacheKey {
url: object
headers: object
}
export const mockCaches = () => {
return {
default: {
async match(key: any) {
let cacheKey: CacheKey = {
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)
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)
}
}
}
// TODO: write test to accomodate for rare scenarios with where range requests accomodate etags
if (response && !key.headers.has('if-none-match')) {
// 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
}
let etag = response.headers.get('etag')
if (etag && !etag.includes('W/')) {
response.headers.set('etag', `W/${etag}`)
}
}
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 cacheKey: CacheKey = {
url: key.url,
headers: {
etag: `"${url.pathname.replace('/', '')}"`,
},
}
cacheStore.set(JSON.stringify(cacheKey), resNoBody)
cacheKey.headers = {}
cacheStore.set(JSON.stringify(cacheKey), resWithBody)
return
},
},
}
}
// mocks functionality used inside worker request
export function mockRequestScope() {
Object.assign(global, makeServiceWorkerEnv())
Object.assign(global, { __STATIC_CONTENT_MANIFEST: mockManifest() })
Object.assign(global, { __STATIC_CONTENT: mockKV(store) })
Object.assign(global, { caches: mockCaches() })
}
// mocks functionality used on global isolate scope. such as the KV namespace bind
export function mockGlobalScope() {
Object.assign(global, { __STATIC_CONTENT_MANIFEST: mockManifest() })
Object.assign(global, { __STATIC_CONTENT: mockKV(store) })
}
export const sleep = (milliseconds: number) => {
return new Promise((resolve) => setTimeout(resolve, milliseconds))
}
|