File size: 6,402 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
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sleep = exports.mockGlobalScope = exports.mockRequestScope = exports.mockCaches = exports.mockManifest = exports.mockKV = exports.getEvent = void 0;
const makeServiceWorkerEnv = require('service-worker-mock');
const HASH = '123HASHBROWN';
const getEvent = (request) => {
    const waitUntil = async (callback) => {
        await callback;
    };
    return {
        request,
        waitUntil,
    };
};
exports.getEvent = getEvent;
const store = {
    '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',
};
const mockKV = (store) => {
    return {
        get: (path) => store[path] || null,
    };
};
exports.mockKV = mockKV;
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`,
    });
};
exports.mockManifest = mockManifest;
let cacheStore = new Map();
const mockCaches = () => {
    return {
        default: {
            async match(key) {
                let 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.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, val) {
                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 = {
                    url: key.url,
                    headers: {
                        etag: `"${url.pathname.replace('/', '')}"`,
                    },
                };
                cacheStore.set(JSON.stringify(cacheKey), resNoBody);
                cacheKey.headers = {};
                cacheStore.set(JSON.stringify(cacheKey), resWithBody);
                return;
            },
        },
    };
};
exports.mockCaches = mockCaches;
// mocks functionality used inside worker request
function mockRequestScope() {
    Object.assign(global, makeServiceWorkerEnv());
    Object.assign(global, { __STATIC_CONTENT_MANIFEST: (0, exports.mockManifest)() });
    Object.assign(global, { __STATIC_CONTENT: (0, exports.mockKV)(store) });
    Object.assign(global, { caches: (0, exports.mockCaches)() });
}
exports.mockRequestScope = mockRequestScope;
// mocks functionality used on global isolate scope. such as the KV namespace bind
function mockGlobalScope() {
    Object.assign(global, { __STATIC_CONTENT_MANIFEST: (0, exports.mockManifest)() });
    Object.assign(global, { __STATIC_CONTENT: (0, exports.mockKV)(store) });
}
exports.mockGlobalScope = mockGlobalScope;
const sleep = (milliseconds) => {
    return new Promise((resolve) => setTimeout(resolve, milliseconds));
};
exports.sleep = sleep;