mocks.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.sleep = exports.mockGlobalScope = exports.mockRequestScope = exports.mockCaches = exports.mockManifest = exports.mockKV = exports.getEvent = void 0;
  4. const makeServiceWorkerEnv = require('service-worker-mock');
  5. const HASH = '123HASHBROWN';
  6. const getEvent = (request) => {
  7. const waitUntil = async (callback) => {
  8. await callback;
  9. };
  10. return {
  11. request,
  12. waitUntil,
  13. };
  14. };
  15. exports.getEvent = getEvent;
  16. const store = {
  17. 'key1.123HASHBROWN.txt': 'val1',
  18. 'key1.123HASHBROWN.png': 'val1',
  19. 'index.123HASHBROWN.html': 'index.html',
  20. 'cache.123HASHBROWN.html': 'cache me if you can',
  21. '测试.123HASHBROWN.html': 'My filename is non-ascii',
  22. '%not-really-percent-encoded.123HASHBROWN.html': 'browser percent encoded',
  23. '%2F.123HASHBROWN.html': 'user percent encoded',
  24. '你好.123HASHBROWN.html': 'I shouldnt be served',
  25. '%E4%BD%A0%E5%A5%BD.123HASHBROWN.html': 'Im important',
  26. 'nohash.txt': 'no hash but still got some result',
  27. 'sub/blah.123HASHBROWN.png': 'picturedis',
  28. 'sub/index.123HASHBROWN.html': 'picturedis',
  29. 'client.123HASHBROWN': 'important file',
  30. 'client.123HASHBROWN/index.html': 'Im here but serve my big bro above',
  31. 'image.123HASHBROWN.png': 'imagepng',
  32. 'image.123HASHBROWN.webp': 'imagewebp',
  33. '你好/index.123HASHBROWN.html': 'My path is non-ascii',
  34. };
  35. const mockKV = (store) => {
  36. return {
  37. get: (path) => store[path] || null,
  38. };
  39. };
  40. exports.mockKV = mockKV;
  41. const mockManifest = () => {
  42. return JSON.stringify({
  43. 'key1.txt': `key1.${HASH}.txt`,
  44. 'key1.png': `key1.${HASH}.png`,
  45. 'cache.html': `cache.${HASH}.html`,
  46. '测试.html': `测试.${HASH}.html`,
  47. '你好.html': `你好.${HASH}.html`,
  48. '%not-really-percent-encoded.html': `%not-really-percent-encoded.${HASH}.html`,
  49. '%2F.html': `%2F.${HASH}.html`,
  50. '%E4%BD%A0%E5%A5%BD.html': `%E4%BD%A0%E5%A5%BD.${HASH}.html`,
  51. 'index.html': `index.${HASH}.html`,
  52. 'sub/blah.png': `sub/blah.${HASH}.png`,
  53. 'sub/index.html': `sub/index.${HASH}.html`,
  54. client: `client.${HASH}`,
  55. 'client/index.html': `client.${HASH}`,
  56. 'image.png': `image.${HASH}.png`,
  57. 'image.webp': `image.${HASH}.webp`,
  58. '你好/index.html': `你好/index.${HASH}.html`,
  59. });
  60. };
  61. exports.mockManifest = mockManifest;
  62. let cacheStore = new Map();
  63. const mockCaches = () => {
  64. return {
  65. default: {
  66. async match(key) {
  67. let cacheKey = {
  68. url: key.url,
  69. headers: {},
  70. };
  71. let response;
  72. if (key.headers.has('if-none-match')) {
  73. let makeStrongEtag = key.headers.get('if-none-match').replace('W/', '');
  74. Reflect.set(cacheKey.headers, 'etag', makeStrongEtag);
  75. response = cacheStore.get(JSON.stringify(cacheKey));
  76. }
  77. else {
  78. // if client doesn't send if-none-match, we need to iterate through these keys
  79. // and just test the URL
  80. const activeCacheKeys = Array.from(cacheStore.keys());
  81. for (const cacheStoreKey of activeCacheKeys) {
  82. if (JSON.parse(cacheStoreKey).url === key.url) {
  83. response = cacheStore.get(cacheStoreKey);
  84. }
  85. }
  86. }
  87. // TODO: write test to accomodate for rare scenarios with where range requests accomodate etags
  88. if (response && !key.headers.has('if-none-match')) {
  89. // this appears overly verbose, but is necessary to document edge cache behavior
  90. // The Range request header triggers the response header Content-Range ...
  91. const range = key.headers.get('range');
  92. if (range) {
  93. response.headers.set('content-range', `bytes ${range.split('=').pop()}/${response.headers.get('content-length')}`);
  94. }
  95. // ... which we are using in this repository to set status 206
  96. if (response.headers.has('content-range')) {
  97. response.status = 206;
  98. }
  99. else {
  100. response.status = 200;
  101. }
  102. let etag = response.headers.get('etag');
  103. if (etag && !etag.includes('W/')) {
  104. response.headers.set('etag', `W/${etag}`);
  105. }
  106. }
  107. return response;
  108. },
  109. async put(key, val) {
  110. let headers = new Headers(val.headers);
  111. let url = new URL(key.url);
  112. let resWithBody = new Response(val.body, { headers, status: 200 });
  113. let resNoBody = new Response(null, { headers, status: 304 });
  114. let cacheKey = {
  115. url: key.url,
  116. headers: {
  117. etag: `"${url.pathname.replace('/', '')}"`,
  118. },
  119. };
  120. cacheStore.set(JSON.stringify(cacheKey), resNoBody);
  121. cacheKey.headers = {};
  122. cacheStore.set(JSON.stringify(cacheKey), resWithBody);
  123. return;
  124. },
  125. },
  126. };
  127. };
  128. exports.mockCaches = mockCaches;
  129. // mocks functionality used inside worker request
  130. function mockRequestScope() {
  131. Object.assign(global, makeServiceWorkerEnv());
  132. Object.assign(global, { __STATIC_CONTENT_MANIFEST: (0, exports.mockManifest)() });
  133. Object.assign(global, { __STATIC_CONTENT: (0, exports.mockKV)(store) });
  134. Object.assign(global, { caches: (0, exports.mockCaches)() });
  135. }
  136. exports.mockRequestScope = mockRequestScope;
  137. // mocks functionality used on global isolate scope. such as the KV namespace bind
  138. function mockGlobalScope() {
  139. Object.assign(global, { __STATIC_CONTENT_MANIFEST: (0, exports.mockManifest)() });
  140. Object.assign(global, { __STATIC_CONTENT: (0, exports.mockKV)(store) });
  141. }
  142. exports.mockGlobalScope = mockGlobalScope;
  143. const sleep = (milliseconds) => {
  144. return new Promise((resolve) => setTimeout(resolve, milliseconds));
  145. };
  146. exports.sleep = sleep;