wooks 0.0.1-beta.6 → 0.0.1-beta.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +45 -24
  2. package/dist/src/index.d.ts +0 -6
  3. package/dist/src/index.d.ts.map +1 -1
  4. package/dist/src/types.d.ts +1 -1
  5. package/dist/src/types.d.ts.map +1 -1
  6. package/dist/src/wooks.d.ts +5 -0
  7. package/dist/src/wooks.d.ts.map +1 -1
  8. package/dist/wooks.cjs.prod.js +24 -2766
  9. package/dist/wooks.d.ts +7 -559
  10. package/dist/wooks.esm-bundler.js +26 -2737
  11. package/package.json +8 -5
  12. package/dist/src/composables/body.d.ts +0 -17
  13. package/dist/src/composables/body.d.ts.map +0 -1
  14. package/dist/src/composables/cookies.d.ts +0 -14
  15. package/dist/src/composables/cookies.d.ts.map +0 -1
  16. package/dist/src/composables/core-test.d.ts +0 -19
  17. package/dist/src/composables/core-test.d.ts.map +0 -1
  18. package/dist/src/composables/core.d.ts +0 -30
  19. package/dist/src/composables/core.d.ts.map +0 -1
  20. package/dist/src/composables/header-accept.d.ts +0 -9
  21. package/dist/src/composables/header-accept.d.ts.map +0 -1
  22. package/dist/src/composables/header-authorization.d.ts +0 -20
  23. package/dist/src/composables/header-authorization.d.ts.map +0 -1
  24. package/dist/src/composables/header-set-cache-control.d.ts +0 -9
  25. package/dist/src/composables/header-set-cache-control.d.ts.map +0 -1
  26. package/dist/src/composables/headers.d.ts +0 -11
  27. package/dist/src/composables/headers.d.ts.map +0 -1
  28. package/dist/src/composables/hooks.d.ts +0 -20
  29. package/dist/src/composables/hooks.d.ts.map +0 -1
  30. package/dist/src/composables/index.d.ts +0 -13
  31. package/dist/src/composables/index.d.ts.map +0 -1
  32. package/dist/src/composables/proxy-utils.d.ts +0 -25
  33. package/dist/src/composables/proxy-utils.d.ts.map +0 -1
  34. package/dist/src/composables/proxy.d.ts +0 -12
  35. package/dist/src/composables/proxy.d.ts.map +0 -1
  36. package/dist/src/composables/req-res.d.ts +0 -34
  37. package/dist/src/composables/req-res.d.ts.map +0 -1
  38. package/dist/src/composables/search-params.d.ts +0 -13
  39. package/dist/src/composables/search-params.d.ts.map +0 -1
  40. package/dist/src/composables/tests/body.spec.d.ts +0 -2
  41. package/dist/src/composables/tests/body.spec.d.ts.map +0 -1
  42. package/dist/src/composables/tests/cookies.spec.d.ts +0 -2
  43. package/dist/src/composables/tests/cookies.spec.d.ts.map +0 -1
  44. package/dist/src/composables/tests/core.spec.d.ts +0 -2
  45. package/dist/src/composables/tests/core.spec.d.ts.map +0 -1
  46. package/dist/src/composables/tests/headers.spec.d.ts +0 -2
  47. package/dist/src/composables/tests/headers.spec.d.ts.map +0 -1
  48. package/dist/src/composables/tests/proxy.spec.d.ts +0 -2
  49. package/dist/src/composables/tests/proxy.spec.d.ts.map +0 -1
  50. package/dist/src/composables/tests/req-res.spec.d.ts +0 -2
  51. package/dist/src/composables/tests/req-res.spec.d.ts.map +0 -1
  52. package/dist/src/composables/tests/search-params.spec.d.ts +0 -2
  53. package/dist/src/composables/tests/search-params.spec.d.ts.map +0 -1
  54. package/dist/src/content-types/index.d.ts +0 -97
  55. package/dist/src/content-types/index.d.ts.map +0 -1
  56. package/dist/src/errors/error-renderer.d.ts +0 -9
  57. package/dist/src/errors/error-renderer.d.ts.map +0 -1
  58. package/dist/src/errors/errors.spec.d.ts +0 -2
  59. package/dist/src/errors/errors.spec.d.ts.map +0 -1
  60. package/dist/src/errors/index.d.ts +0 -3
  61. package/dist/src/errors/index.d.ts.map +0 -1
  62. package/dist/src/errors/wooks-error.d.ts +0 -20
  63. package/dist/src/errors/wooks-error.d.ts.map +0 -1
  64. package/dist/src/mime/extensions.d.ts +0 -1184
  65. package/dist/src/mime/extensions.d.ts.map +0 -1
  66. package/dist/src/mime/index.d.ts +0 -2
  67. package/dist/src/mime/index.d.ts.map +0 -1
  68. package/dist/src/mime/mime.spec.d.ts +0 -2
  69. package/dist/src/mime/mime.spec.d.ts.map +0 -1
  70. package/dist/src/response/core.d.ts +0 -30
  71. package/dist/src/response/core.d.ts.map +0 -1
  72. package/dist/src/response/factory.d.ts +0 -4
  73. package/dist/src/response/factory.d.ts.map +0 -1
  74. package/dist/src/response/index.d.ts +0 -4
  75. package/dist/src/response/index.d.ts.map +0 -1
  76. package/dist/src/response/renderer.d.ts +0 -8
  77. package/dist/src/response/renderer.d.ts.map +0 -1
  78. package/dist/src/response/response.spec.d.ts +0 -2
  79. package/dist/src/response/response.spec.d.ts.map +0 -1
  80. package/dist/src/serve-file/serve-file.d.ts +0 -20
  81. package/dist/src/serve-file/serve-file.d.ts.map +0 -1
  82. package/dist/src/serve-file/serve-file.spec.d.ts +0 -2
  83. package/dist/src/serve-file/serve-file.spec.d.ts.map +0 -1
  84. package/dist/src/status-codes/index.d.ts +0 -135
  85. package/dist/src/status-codes/index.d.ts.map +0 -1
  86. package/dist/src/utils/body-compressor.d.ts +0 -8
  87. package/dist/src/utils/body-compressor.d.ts.map +0 -1
  88. package/dist/src/utils/cache-control.d.ts +0 -14
  89. package/dist/src/utils/cache-control.d.ts.map +0 -1
  90. package/dist/src/utils/set-cookie.d.ts +0 -16
  91. package/dist/src/utils/set-cookie.d.ts.map +0 -1
  92. package/dist/src/utils/tests/body-compressor.spec.d.ts +0 -2
  93. package/dist/src/utils/tests/body-compressor.spec.d.ts.map +0 -1
  94. package/dist/src/utils/tests/set-cookie.spec.d.ts +0 -2
  95. package/dist/src/utils/tests/set-cookie.spec.d.ts.map +0 -1
  96. package/dist/src/utils/tests/time.spec.d.ts +0 -2
  97. package/dist/src/utils/tests/time.spec.d.ts.map +0 -1
  98. package/dist/src/utils/tests/url-search-params.spec.d.ts +0 -2
  99. package/dist/src/utils/tests/url-search-params.spec.d.ts.map +0 -1
  100. package/dist/src/utils/time.d.ts +0 -5
  101. package/dist/src/utils/time.d.ts.map +0 -1
  102. package/dist/src/utils/url-search-params.d.ts +0 -6
  103. package/dist/src/utils/url-search-params.d.ts.map +0 -1
@@ -3,87 +3,12 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var router = require('@prostojs/router');
6
+ var composables = require('@wooksjs/composables');
6
7
  var http = require('http');
7
- var crypto = require('crypto');
8
- var stream = require('stream');
9
- var fs = require('fs');
10
- var path = require('path');
11
- var url = require('url');
12
- var net = require('net');
13
- var nodeFetchNative = require('node-fetch-native');
14
8
 
15
9
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e["default"] : e; }
16
10
 
17
11
  var http__default = /*#__PURE__*/_interopDefaultLegacy(http);
18
- var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
19
-
20
- const banner = () => `[wooks][${new Date().toISOString().replace('T', ' ').replace(/\.\d{3}z$/i, '')}] `;
21
-
22
- function warn(text) {
23
- console.warn('' + banner() + text + '');
24
- }
25
- function logError(error) {
26
- console.error('' + '' + banner() + error + '');
27
- }
28
-
29
- function panic(error) {
30
- logError(error);
31
- return new Error(error);
32
- }
33
-
34
- let currentHttpContext = null;
35
- function useCurrentWooksContext() {
36
- if (!currentHttpContext) {
37
- throw panic('Use HTTP hooks only synchronously within the runtime of the request.');
38
- }
39
- const cc = currentHttpContext;
40
- return {
41
- getCtx: () => cc,
42
- restoreCtx: () => setCurrentWooksContext(cc.req, cc.res, cc.params, cc.customContext),
43
- };
44
- }
45
- function clearCurrentWooksContext() {
46
- currentHttpContext = null;
47
- }
48
- function setCurrentWooksContext(req, res, params, customContext) {
49
- currentHttpContext = { req, res, params, customContext };
50
- }
51
- const innerCacheSymbols = {
52
- searchParams: Symbol('searchParams'),
53
- cookies: Symbol('cookies'),
54
- accept: Symbol('accept'),
55
- authorization: Symbol('authorization'),
56
- setHeader: Symbol('setHeader'),
57
- setCookies: Symbol('setCookies'),
58
- status: Symbol('status'),
59
- response: Symbol('response'),
60
- request: Symbol('request'),
61
- };
62
- function useCacheObject(name) {
63
- const cc = useCurrentWooksContext().getCtx().customContext;
64
- const cache = cc[name] = (cc[name] || {});
65
- return cache;
66
- }
67
- function clearCacheObject(name) {
68
- const cc = useCurrentWooksContext().getCtx().customContext;
69
- const o = cc[name];
70
- switch (typeof o) {
71
- case 'object':
72
- if (Array.isArray(o)) {
73
- o.splice(0, o.length);
74
- }
75
- else {
76
- for (const key in o) {
77
- delete o[key];
78
- }
79
- }
80
- break;
81
- case 'string':
82
- cc[name] = '';
83
- break;
84
- default: cc[name] = {};
85
- }
86
- }
87
12
 
88
13
  function createServer(opts, cb, hostname, onListen) {
89
14
  const server = http__default.createServer(cb);
@@ -96,1317 +21,22 @@ function createServer(opts, cb, hostname, onListen) {
96
21
  return server;
97
22
  }
98
23
 
99
- const contentTypes = {
100
- application: {
101
- atomXml: 'application/atom+xml',
102
- ediX12: 'application/EDI-X12',
103
- edifact: 'application/EDIFACT',
104
- json: 'application/json',
105
- javascript: 'application/javascript',
106
- octetStream: 'application/octet-stream',
107
- ogg: 'application/ogg',
108
- pdf: 'application/pdf',
109
- postscript: 'application/postscript',
110
- soapXml: 'application/soap+xml',
111
- fontWoff: 'application/font-woff',
112
- xhtmlXml: 'application/xhtml+xml',
113
- xmlDtd: 'application/xml-dtd',
114
- xopXml: 'application/xop+xml',
115
- zip: 'application/zip',
116
- gzip: 'application/gzip',
117
- xBittorrent: 'application/x-bittorrent',
118
- xTex: 'application/x-tex',
119
- xml: 'application/xml',
120
- msword: 'application/msword',
121
- xWwwFormUrlencoded: 'application/x-www-form-urlencoded',
122
- xDvi: 'application/x-dvi',
123
- xLatex: 'application/x-latex',
124
- xFontTtf: 'application/x-font-ttf',
125
- xShockwaveFlash: 'application/x-shockwave-flash',
126
- xStuffit: 'application/x-stuffit',
127
- xRarCompressed: 'application/x-rar-compressed',
128
- xTar: 'application/x-tar',
129
- xJavascript: 'application/x-javascript',
130
- },
131
- audio: {
132
- basic: 'audio/basic',
133
- L24: 'audio/L24',
134
- mp4: 'audio/mp4',
135
- aac: 'audio/aac',
136
- mpeg: 'audio/mpeg',
137
- ogg: 'audio/ogg',
138
- vorbis: 'audio/vorbis',
139
- xMsWma: 'audio/x-ms-wma',
140
- xMsWax: 'audio/x-ms-wax',
141
- vndRnRealaudio: 'audio/vnd.rn-realaudio',
142
- vndWave: 'audio/vnd.wave',
143
- webm: 'audio/webm',
144
- },
145
- image: {
146
- gif: 'image/gif',
147
- jpeg: 'image/jpeg',
148
- pjpeg: 'image/pjpeg',
149
- png: 'image/png',
150
- svgXml: 'image/svg+xml',
151
- tiff: 'image/tiff',
152
- vndMicrosoftIcon: 'image/vnd.microsoft.icon',
153
- vndWapWbmp: 'image/vnd.wap.wbmp',
154
- webp: 'image/webp',
155
- },
156
- message: {
157
- http: 'message/http',
158
- imdnXml: 'message/imdn+xml',
159
- partial: 'message/partial',
160
- rfc822: 'message/rfc822',
161
- },
162
- model: {
163
- example: 'model/example',
164
- iges: 'model/iges',
165
- mesh: 'model/mesh',
166
- vrml: 'model/vrml',
167
- x3dBinary: 'model/x3d+binary',
168
- x3dVrml: 'model/x3d+vrml',
169
- x3dXml: 'model/x3d+xml',
170
- },
171
- text: {
172
- cmd: 'text/cmd',
173
- css: 'text/css',
174
- csv: 'text/csv',
175
- html: 'text/html',
176
- plain: 'text/plain',
177
- php: 'text/php',
178
- xml: 'text/xml',
179
- markdown: 'text/markdown',
180
- cacheManifest: 'text/cache-manifest',
181
- },
182
- video: {
183
- mpeg: 'video/mpeg',
184
- mp4: 'video/mp4',
185
- ogg: 'video/ogg',
186
- quicktime: 'video/quicktime',
187
- webm: 'video/webm',
188
- xMsWmv: 'video/x-ms-wmv',
189
- xFlv: 'video/x-flv',
190
- xMsvideo: 'video/x-msvideo',
191
- threeGpp: 'video/3gpp',
192
- threeGpp2: 'video/3gpp2',
193
- },
194
- };
195
-
196
- class BaseWooksResponseRenderer {
197
- render(response) {
198
- if (typeof response.body === 'string' || typeof response.body === 'boolean' || typeof response.body === 'number') {
199
- if (!response.getContentType())
200
- response.setContentType(contentTypes.text.plain);
201
- return response.body.toString();
202
- }
203
- if (typeof response.body === 'undefined') {
204
- return '';
205
- }
206
- if (response.body instanceof Uint8Array) {
207
- return response.body;
208
- }
209
- if (typeof response.body === 'object') {
210
- if (!response.getContentType())
211
- response.setContentType(contentTypes.application.json);
212
- return JSON.stringify(response.body);
213
- }
214
- throw panic('Unsupported body format "' + typeof response.body + '"');
215
- }
216
- }
217
-
218
- const xForwardedFor = 'x-forwarded-for';
219
- function useRequest() {
220
- const reqCache = useCacheObject(innerCacheSymbols.request);
221
- const { req, customContext } = useCurrentWooksContext().getCtx();
222
- async function rawBody() {
223
- if (typeof reqCache.rawBody === 'undefined') {
224
- reqCache.rawBody = new Promise((resolve, reject) => {
225
- let body = Buffer.from('');
226
- req.on('data', function (chunk) {
227
- body = Buffer.concat([body, chunk]);
228
- });
229
- req.on('error', function (err) {
230
- reject(err);
231
- });
232
- req.on('end', function () {
233
- resolve(body);
234
- });
235
- });
236
- }
237
- return reqCache.rawBody;
238
- }
239
- function reqId() {
240
- if (!reqCache.reqId) {
241
- reqCache.reqId = crypto.randomUUID();
242
- }
243
- return reqCache.reqId;
244
- }
245
- function getIp(options) {
246
- if (options?.trustProxy) {
247
- if (typeof reqCache.forwardedIp !== 'string') {
248
- if (typeof req.headers[xForwardedFor] === 'string' && req.headers[xForwardedFor]) {
249
- reqCache.forwardedIp = req.headers[xForwardedFor].split(',').shift()?.trim();
250
- }
251
- else {
252
- return getIp();
253
- }
254
- }
255
- return reqCache.forwardedIp || '';
256
- }
257
- else {
258
- if (typeof reqCache.remoteIp !== 'string') {
259
- reqCache.remoteIp = req.socket?.remoteAddress || req.connection?.remoteAddress || '';
260
- }
261
- return reqCache.remoteIp;
262
- }
263
- }
264
- function getIpList() {
265
- if (!reqCache.ipList) {
266
- reqCache.ipList = {
267
- remoteIp: req.socket?.remoteAddress || req.connection?.remoteAddress || '',
268
- forwarded: (req.headers[xForwardedFor] || '').split(',').map(s => s.trim()),
269
- };
270
- }
271
- return reqCache.ipList;
272
- }
273
- return {
274
- rawRequest: req,
275
- url: req.url,
276
- method: req.method,
277
- headers: req.headers,
278
- rawBody,
279
- reqId,
280
- getIp,
281
- getIpList,
282
- customContext,
283
- };
284
- }
285
- function useResponse() {
286
- const cache = useCacheObject(innerCacheSymbols.response);
287
- const res = useCurrentWooksContext().getCtx().res;
288
- const statusCache = useCacheObject(innerCacheSymbols.status);
289
- function status(code) {
290
- if (code) {
291
- statusCache.code = code;
292
- }
293
- return statusCache.code;
294
- }
295
- const rawResponse = (options) => {
296
- if (!options || !options.passthrough)
297
- cache.responded = true;
298
- return res;
299
- };
300
- const hasResponded = () => cache.responded;
301
- return {
302
- rawResponse,
303
- hasResponded,
304
- status,
305
- };
306
- }
307
- function useRouteParams() {
308
- const routeParams = useCurrentWooksContext().getCtx().params;
309
- function getRouteParam(name) {
310
- return routeParams[name];
311
- }
312
- return {
313
- routeParams,
314
- getRouteParam,
315
- };
316
- }
317
-
318
- function useHeaders() {
319
- return useRequest().headers;
320
- }
321
- function useSetHeaders() {
322
- const cache = useCacheObject(innerCacheSymbols.setHeader);
323
- function setHeader(name, value) {
324
- cache[name] = value.toString();
325
- }
326
- function removeHeader(name) {
327
- delete cache[name];
328
- }
329
- function setContentType(value) {
330
- setHeader('content-type', value);
331
- }
332
- function enableCors(origin = '*') {
333
- setHeader('access-control-allow-origin', origin);
334
- }
335
- return {
336
- setHeader,
337
- removeHeader,
338
- setContentType,
339
- headers: cache,
340
- enableCors,
341
- };
342
- }
343
-
344
- function useAccept() {
345
- const { accept } = useHeaders();
346
- const cache = useCacheObject(innerCacheSymbols.accept);
347
- const accepts = (mime) => {
348
- if (typeof cache[mime] !== 'boolean') {
349
- cache[mime] = !!(accept && (accept === '*/*' || accept.indexOf(mime) >= 0));
350
- }
351
- return cache[mime];
352
- };
353
- return {
354
- accept,
355
- accepts,
356
- acceptsJson: () => accepts(contentTypes.application.json),
357
- acceptsXml: () => accepts(contentTypes.application.xml),
358
- acceptsText: () => accepts(contentTypes.text.plain),
359
- acceptsHtml: () => accepts(contentTypes.text.html),
360
- };
361
- }
362
-
363
- function useAuthorization() {
364
- const { authorization } = useHeaders();
365
- const cache = useCacheObject(innerCacheSymbols.authorization);
366
- const authType = () => {
367
- if (authorization) {
368
- if (typeof cache.type === 'undefined') {
369
- const space = authorization.indexOf(' ');
370
- cache.type = authorization.slice(0, space);
371
- }
372
- return cache.type;
373
- }
374
- return null;
375
- };
376
- const authRawCredentials = () => {
377
- if (authorization) {
378
- if (typeof cache.credentials === 'undefined') {
379
- const space = authorization.indexOf(' ');
380
- cache.credentials = authorization.slice(space + 1);
381
- }
382
- return cache.credentials;
383
- }
384
- return null;
385
- };
386
- return {
387
- authorization,
388
- authType,
389
- authRawCredentials,
390
- isBasic: () => authType()?.toLocaleLowerCase() === 'basic',
391
- isBearer: () => authType()?.toLocaleLowerCase() === 'bearer',
392
- basicCredentials: () => {
393
- if (authorization) {
394
- if (typeof cache.basicCredentials === 'undefined') {
395
- const type = authType();
396
- if (type?.toLocaleLowerCase() === 'basic') {
397
- const creds = Buffer.from(authRawCredentials() || '', 'base64').toString('ascii');
398
- const [username, password] = creds.split(':');
399
- cache.basicCredentials = { username, password };
400
- }
401
- }
402
- return cache.basicCredentials;
403
- }
404
- return null;
405
- },
406
- };
407
- }
408
-
409
- function convertTime(time, unit = 'ms') {
410
- if (typeof time === 'number')
411
- return time / units[unit];
412
- const rg = /(\d+)(\w+)/g;
413
- let t = 0;
414
- let r;
415
- while (r = rg.exec(time)) {
416
- t += Number(r[1]) * (units[r[2]] || 0);
417
- }
418
- return t / units[unit];
419
- }
420
- const units = {
421
- ms: 1,
422
- s: 1000,
423
- m: 1000 * 60,
424
- h: 1000 * 60 * 60,
425
- d: 1000 * 60 * 60 * 24,
426
- w: 1000 * 60 * 60 * 24 * 7,
427
- M: 1000 * 60 * 60 * 24 * 30,
428
- Y: 1000 * 60 * 60 * 24 * 365,
429
- };
430
-
431
- function renderCacheControl(data) {
432
- let attrs = '';
433
- for (const [a, v] of Object.entries(data)) {
434
- if (typeof v === 'undefined')
435
- continue;
436
- const func = cacheControlFunc[a];
437
- if (typeof func === 'function') {
438
- const val = func(v);
439
- if (val) {
440
- attrs += attrs ? ', ' + val : val;
441
- }
442
- }
443
- else {
444
- panic('Unknown Cache-Control attribute ' + a);
445
- }
446
- }
447
- return attrs;
448
- }
449
- const cacheControlFunc = {
450
- mustRevalidate: (v) => v ? 'must-revalidate' : '',
451
- noCache: (v) => v ? (typeof v === 'string' ? `no-cache="${v}"` : 'no-cache') : '',
452
- noStore: (v) => v ? 'no-store' : '',
453
- noTransform: (v) => v ? 'no-transform' : '',
454
- public: (v) => v ? 'public' : '',
455
- private: (v) => v ? (typeof v === 'string' ? `private="${v}"` : 'private') : '',
456
- proxyRevalidate: (v) => v ? 'proxy-revalidate' : '',
457
- maxAge: (v) => 'max-age=' + convertTime(v, 's').toString(),
458
- sMaxage: (v) => 's-maxage=' + convertTime(v, 's').toString(),
459
- };
460
-
461
- const renderAge = (v) => convertTime(v, 's').toString();
462
- const renderExpires = (v) => (typeof v === 'string' || typeof v === 'number' ? new Date(v).toUTCString() : v.toUTCString());
463
- const renderPragmaNoCache = (v) => v ? 'no-cache' : '';
464
- function useSetCacheControl() {
465
- const { setHeader } = useSetHeaders();
466
- const setAge = (value) => {
467
- setHeader('age', renderAge(value));
468
- };
469
- const setExpires = (value) => {
470
- setHeader('expires', renderExpires(value));
471
- };
472
- const setPragmaNoCache = (value = true) => {
473
- setHeader('pragma', renderPragmaNoCache(value));
474
- };
475
- const setCacheControl = (data) => {
476
- setHeader('cache-control', renderCacheControl(data));
477
- };
478
- return {
479
- setExpires,
480
- setAge,
481
- setPragmaNoCache,
482
- setCacheControl,
483
- };
484
- }
485
-
486
- function renderCookie(key, data) {
487
- let attrs = '';
488
- for (const [a, v] of Object.entries(data.attrs)) {
489
- const func = cookieAttrFunc[a];
490
- if (typeof func === 'function') {
491
- const val = func(v);
492
- attrs += val ? '; ' + val : '';
493
- }
494
- else {
495
- panic('Unknown Set-Cookie attribute ' + a);
496
- }
497
- }
498
- return `${key}=${encodeURIComponent(data.value)}${attrs}`;
499
- }
500
- const cookieAttrFunc = {
501
- expires: (v) => 'Expires=' + (typeof v === 'string' || typeof v === 'number' ? new Date(v).toUTCString() : v.toUTCString()),
502
- maxAge: (v) => 'Max-Age=' + convertTime(v, 's').toString(),
503
- domain: (v) => 'Domain=' + v,
504
- path: (v) => 'Path=' + v,
505
- secure: (v) => v ? 'Secure' : '',
506
- httpOnly: (v) => v ? 'HttpOnly' : '',
507
- sameSite: (v) => v ? 'SameSite=' + (typeof v === 'string' ? v : 'Strict') : '',
508
- };
509
-
510
- function useCookies() {
511
- const cache = useCacheObject(innerCacheSymbols.cookies);
512
- const { cookie } = useHeaders();
513
- function getCookie(name) {
514
- if (typeof cache[name] === 'undefined') {
515
- if (cookie) {
516
- const result = new RegExp(`(?:^|; )${router.escapeRegex(name)}=(.*?)(?:;?$|; )`, 'i').exec(cookie);
517
- cache[name] = result && result[1] ? router.safeDecodeURIComponent(result[1]) : null;
518
- }
519
- else {
520
- cache[name] = null;
521
- }
522
- }
523
- return cache[name];
524
- }
525
- return {
526
- rawCookies: cookie,
527
- getCookie,
528
- };
529
- }
530
- function useSetCookies() {
531
- const cache = useCacheObject(innerCacheSymbols.setCookies);
532
- function setCookie(name, value, attrs) {
533
- cache[name] = {
534
- value,
535
- attrs: attrs || {},
536
- };
537
- }
538
- function getCookie(name) {
539
- return cache[name];
540
- }
541
- function cookies() {
542
- return Object.entries(cache).map(([key, value]) => renderCookie(key, value));
543
- }
544
- function removeCookie(name) {
545
- delete cache[name];
546
- }
547
- function clearCookies() {
548
- clearCacheObject(innerCacheSymbols.setCookies);
549
- }
550
- return {
551
- setCookie,
552
- getCookie,
553
- removeCookie,
554
- clearCookies,
555
- cookies,
556
- };
557
- }
558
-
559
- class ProstoURLSearchParams extends url.URLSearchParams {
560
- toJson() {
561
- const json = {};
562
- for (const [key, value] of this.entries()) {
563
- if (isArrayParam(key)) {
564
- const a = json[key] = (json[key] || []);
565
- a.push(value);
566
- }
567
- else {
568
- json[key] = value;
569
- }
570
- }
571
- return json;
572
- }
573
- }
574
- function isArrayParam(name) {
575
- return name.endsWith('[]');
576
- }
577
-
578
- function useSearchParams() {
579
- const url = useRequest().url || '';
580
- const cache = useCacheObject(innerCacheSymbols.searchParams);
581
- function rawSearchParams() {
582
- if (typeof cache.raw === 'undefined') {
583
- const i = url.indexOf('?');
584
- cache.raw = i >= 0 ? url.slice(i) : '';
585
- }
586
- return cache.raw;
587
- }
588
- function urlSearchParams() {
589
- if (!cache.urlSearchParams) {
590
- cache.urlSearchParams = new ProstoURLSearchParams(rawSearchParams());
591
- }
592
- return cache.urlSearchParams;
593
- }
594
- return {
595
- rawSearchParams,
596
- urlSearchParams,
597
- jsonSearchParams: () => urlSearchParams().toJson(),
598
- };
599
- }
600
-
601
- const compressors = {
602
- identity: {
603
- compress: v => v,
604
- uncompress: v => v,
605
- },
606
- };
607
- async function uncompressBody(encodings, body) {
608
- let newBody = body;
609
- for (const e of encodings.reverse()) {
610
- if (!compressors[e]) {
611
- throw panic(`Usupported compression type "${e}".`);
612
- }
613
- newBody = await compressors[e].uncompress(body);
614
- }
615
- return newBody;
616
- }
617
-
618
- function useBody() {
619
- const cache = useCacheObject(innerCacheSymbols.request);
620
- const { rawBody } = useRequest();
621
- const { 'content-type': contentType, 'content-encoding': contentEncoding } = useHeaders();
622
- function contentIs(type) {
623
- return (contentType || '').indexOf(type) >= 0;
624
- }
625
- function isJson() {
626
- if (typeof cache.isJson === 'undefined') {
627
- cache.isJson = contentIs(contentTypes.application.json);
628
- }
629
- return cache.isJson;
630
- }
631
- function isHtml() {
632
- if (typeof cache.isHtml === 'undefined') {
633
- cache.isHtml = contentIs(contentTypes.text.html);
634
- }
635
- return cache.isHtml;
636
- }
637
- function isXml() {
638
- if (typeof cache.isXml === 'undefined') {
639
- cache.isXml = contentIs(contentTypes.text.xml);
640
- }
641
- return cache.isXml;
642
- }
643
- function isText() {
644
- if (typeof cache.isText === 'undefined') {
645
- cache.isText = contentIs(contentTypes.text.plain);
646
- }
647
- return cache.isText;
648
- }
649
- function isBinary() {
650
- if (typeof cache.isBinary === 'undefined') {
651
- cache.isBinary = contentIs(contentTypes.application.octetStream);
652
- }
653
- return cache.isBinary;
654
- }
655
- function isFormData() {
656
- if (typeof cache.isFormData === 'undefined') {
657
- cache.isFormData = contentIs('multipart/form-data');
658
- }
659
- return cache.isFormData;
660
- }
661
- function isUrlencoded() {
662
- if (typeof cache.isUrlencoded === 'undefined') {
663
- cache.isUrlencoded = contentIs(contentTypes.application.xWwwFormUrlencoded);
664
- }
665
- return cache.isUrlencoded;
666
- }
667
- function isCompressed() {
668
- if (typeof cache.isCompressed === 'undefined') {
669
- const parts = contentEncodings();
670
- for (const p of parts) {
671
- cache.isCompressed = ['deflate', 'gzip', 'br'].includes(p);
672
- if (cache.isCompressed)
673
- break;
674
- }
675
- }
676
- return cache.isCompressed;
677
- }
678
- function contentEncodings() {
679
- if (typeof cache.contentEncodings === 'undefined') {
680
- cache.contentEncodings = (contentEncoding || '').split(',').map(p => p.trim()).filter(p => !!p);
681
- }
682
- return cache.contentEncodings;
683
- }
684
- async function parseBody() {
685
- if (typeof cache.parsed === 'undefined') {
686
- const body = await uncompressBody(contentEncodings(), (await rawBody()).toString());
687
- if (isJson()) {
688
- cache.parsed = jsonParser(body);
689
- }
690
- else if (isFormData()) {
691
- cache.parsed = formDataParser(body);
692
- }
693
- else if (isUrlencoded()) {
694
- cache.parsed = urlEncodedParser(body);
695
- }
696
- else if (isBinary()) {
697
- cache.parsed = textParser(body);
698
- }
699
- else {
700
- cache.parsed = textParser(body);
701
- }
702
- }
703
- return cache.parsed;
704
- }
705
- function jsonParser(v) {
706
- try {
707
- return JSON.parse(v);
708
- }
709
- catch (e) {
710
- throw new WooksError(400, e.message);
711
- }
712
- }
713
- function textParser(v) {
714
- return v;
715
- }
716
- function formDataParser(v) {
717
- const boundary = '--' + (/boundary=([^;]+)(?:;|$)/.exec(contentType || '') || [, ''])[1];
718
- if (!boundary)
719
- throw new WooksError(exports.EHttpStatusCode.BadRequest, 'form-data boundary not recognized');
720
- const parts = v.trim().split(boundary);
721
- const result = {};
722
- let key = '';
723
- let partContentType = 'text/plain';
724
- for (const part of parts) {
725
- parsePart();
726
- key = '';
727
- partContentType = 'text/plain';
728
- let valueMode = false;
729
- const lines = part.trim().split(/\n/g).map(s => s.trim());
730
- for (const line of lines) {
731
- if (valueMode) {
732
- if (!result[key]) {
733
- result[key] = line;
734
- }
735
- else {
736
- result[key] += '\n' + line;
737
- }
738
- }
739
- else {
740
- if (!line || line === '--') {
741
- valueMode = !!key;
742
- if (valueMode) {
743
- key = key.replace(/^["']/, '').replace(/["']$/, '');
744
- }
745
- continue;
746
- }
747
- if (line.toLowerCase().startsWith('content-disposition: form-data;')) {
748
- key = (/name=([^;]+)/.exec(line) || [])[1];
749
- if (!key)
750
- throw new WooksError(exports.EHttpStatusCode.BadRequest, 'Could not read multipart name: ' + line);
751
- continue;
752
- }
753
- if (line.toLowerCase().startsWith('content-type:')) {
754
- partContentType = (/content-type:\s?([^;]+)/i.exec(line) || [])[1];
755
- if (!partContentType)
756
- throw new WooksError(exports.EHttpStatusCode.BadRequest, 'Could not read content-type: ' + line);
757
- continue;
758
- }
759
- }
760
- }
761
- }
762
- parsePart();
763
- function parsePart() {
764
- if (key) {
765
- if (partContentType.indexOf(contentTypes.application.json) >= 0) {
766
- result[key] = JSON.parse(result[key]);
767
- }
768
- }
769
- }
770
- return result;
771
- }
772
- function urlEncodedParser(v) {
773
- return new ProstoURLSearchParams(v.trim()).toJson();
774
- }
775
- return {
776
- isJson,
777
- isHtml,
778
- isXml,
779
- isText,
780
- isBinary,
781
- isFormData,
782
- isUrlencoded,
783
- isCompressed,
784
- contentEncodings,
785
- parseBody,
786
- rawBody,
787
- };
788
- }
789
- function registerBodyCompressor(name, compressor) {
790
- if (compressors[name]) {
791
- throw panic(`Body compressor "${name}" already registered.`);
792
- }
793
- compressors[name] = compressor;
794
- }
795
-
796
- function setTestHttpContext(options) {
797
- const req = new http.IncomingMessage(new net.Socket({}));
798
- req.method = options.method || 'GET';
799
- req.headers = options.headers || {};
800
- req.url = options.url;
801
- const res = new http.ServerResponse(req);
802
- const cache = {};
803
- if (options.cachedContext) {
804
- const fromInnerContext = [
805
- 'cookies',
806
- 'authorization',
807
- ];
808
- for (const key of Object.keys(options.cachedContext)) {
809
- if (fromInnerContext.includes(key)) {
810
- cache[innerCacheSymbols[key]] = options.cachedContext[key];
811
- }
812
- else if (key === 'body') {
813
- cache[innerCacheSymbols.request] = cache[innerCacheSymbols.request] || {};
814
- Object.assign(cache[innerCacheSymbols.request], { parsed: options.cachedContext[key] });
815
- }
816
- else if (key === 'rawBody') {
817
- cache[innerCacheSymbols.request] = cache[innerCacheSymbols.request] || {};
818
- Object.assign(cache[innerCacheSymbols.request], { rawBody: options.cachedContext[key] });
819
- }
820
- else {
821
- cache[key] = options.cachedContext[key];
822
- }
823
- }
824
- }
825
- setCurrentWooksContext(req, res, options.params || {}, cache);
826
- }
827
-
828
- function useRespCookie(name) {
829
- const { setCookie, getCookie } = useSetCookies();
830
- const hook = {
831
- name,
832
- type: 'cookie',
833
- value: '',
834
- attrs: {},
835
- };
836
- Object.defineProperty(hook, 'value', {
837
- get: () => getCookie(name)?.value,
838
- set: (value) => setCookie(name, value, getCookie(name)?.attrs),
839
- });
840
- Object.defineProperty(hook, 'attrs', {
841
- get: () => getCookie(name)?.attrs,
842
- set: (attrs) => setCookie(name, getCookie(name)?.value || '', attrs),
843
- });
844
- return hook;
845
- }
846
- function useRespHeader(name) {
847
- const { setHeader, headers } = useSetHeaders();
848
- const hook = {
849
- name,
850
- type: 'header',
851
- value: '',
852
- };
853
- Object.defineProperty(hook, 'value', {
854
- get: () => headers[name],
855
- set: (value) => setHeader(name, value),
856
- });
857
- return hook;
858
- }
859
- function useStatus() {
860
- const { status } = useResponse();
861
- const hook = {
862
- name: 'code',
863
- type: 'status',
864
- value: status(),
865
- };
866
- Object.defineProperty(hook, 'value', {
867
- get: () => status(),
868
- set: (code) => status(code),
869
- });
870
- return hook;
871
- }
872
-
873
- class IterableRecords {
874
- [Symbol.iterator]() {
875
- return this;
876
- }
877
- index = 0;
878
- next() {
879
- return { value: undefined, done: true };
880
- }
881
- }
882
- class CookiesIterable extends IterableRecords {
883
- cookies;
884
- constructor(cookiesString) {
885
- super();
886
- this.cookies = cookiesString.split(/,\s(?!\d{2}[\s-])/);
887
- }
888
- next() {
889
- const str = this.cookies[this.index++];
890
- const ind = str ? str.indexOf('=') : 0;
891
- return this.index <= this.cookies.length ?
892
- { value: [str.slice(0, ind), str.slice(ind + 1)], done: false } :
893
- { value: undefined, done: true };
894
- }
895
- }
896
- class HeadersIterable extends IterableRecords {
897
- entries;
898
- constructor(headers) {
899
- super();
900
- this.entries = Object.entries(headers);
901
- }
902
- next() {
903
- return this.index < this.entries.length ?
904
- { value: this.entries[this.index++], done: false } :
905
- { value: undefined, done: true };
906
- }
907
- }
908
- function applyProxyControls(records, controls, additionalBlockers) {
909
- let result = {};
910
- const { allow, block, overwrite } = controls;
911
- const defaultedAllow = allow || '*';
912
- if (defaultedAllow) {
913
- for (const [name, value] of records) {
914
- const add = block !== '*' && (defaultedAllow === '*' ||
915
- (defaultedAllow.find(item => typeof item === 'string' && name.toLowerCase() === item.toLowerCase() || item instanceof RegExp && item.test(name)))) && (!block || !block.find(item => typeof item === 'string' && name.toLowerCase() === item.toLowerCase() || item instanceof RegExp && item.test(name))) && (!additionalBlockers || !additionalBlockers.includes(name));
916
- if (add) {
917
- result[name] = value;
918
- }
919
- }
920
- }
921
- if (overwrite) {
922
- if (typeof overwrite === 'function') {
923
- result = overwrite(result);
924
- }
925
- else {
926
- result = { ...result, ...overwrite };
927
- }
928
- }
929
- return result;
930
- }
931
-
932
- const reqHeadersToBlock = [
933
- 'connection',
934
- 'accept-encoding',
935
- 'content-length',
936
- 'upgrade-insecure-requests',
937
- 'cookie',
938
- ];
939
- const resHeadersToBlock = [
940
- 'transfer-encoding',
941
- 'content-encoding',
942
- 'set-cookie',
943
- ];
944
- function useProxy() {
945
- const status = useStatus();
946
- const { setHeader, headers: setHeadersObject } = useSetHeaders();
947
- const { req } = useCurrentWooksContext().getCtx();
948
- return async function proxy(target, opts) {
949
- const targetUrl = new URL(target);
950
- const path = targetUrl.pathname || '/';
951
- const url = new URL(path, targetUrl.origin).toString() + (targetUrl.search);
952
- const modifiedHeaders = { ...req.headers, host: targetUrl.hostname };
953
- const headers = opts?.reqHeaders ? applyProxyControls(new HeadersIterable(modifiedHeaders), opts?.reqHeaders, reqHeadersToBlock) : {};
954
- const cookies = opts?.reqCookies && req.headers.cookie ? applyProxyControls(new CookiesIterable(req.headers.cookie), opts?.reqCookies) : null;
955
- if (cookies) {
956
- headers.cookie = Object.entries(cookies).map(v => v.join('=')).join('; ');
957
- }
958
- const method = opts?.method || req.method;
959
- if (opts?.debug) {
960
- console.log();
961
- warn(`[proxy] ${''}${req.method} ${req.url}${''} → ${''}${method} ${url}${''}`);
962
- console.log('' + 'headers:', JSON.stringify(headers, null, ' '), '');
963
- }
964
- const resp = await nodeFetchNative.fetch(url, {
965
- method,
966
- body: ['GET', 'HEAD'].includes(method) ? undefined : req,
967
- headers: headers,
968
- });
969
- status.value = resp.status;
970
- if (opts?.debug) {
971
- console.log();
972
- warn(`[proxy] ${resp.status} ${''}${req.method} ${req.url}${''} → ${''}${method} ${url}${''}`);
973
- console.log(`${''}response headers:${''}`);
974
- }
975
- const resHeaders = opts?.resHeaders ? applyProxyControls(resp.headers.entries(), opts?.resHeaders, resHeadersToBlock) : null;
976
- const resCookies = opts?.resCookies ? applyProxyControls(new CookiesIterable(resp.headers.get('set-cookie') || ''), opts?.resCookies) : null;
977
- if (resHeaders) {
978
- for (const [name, value] of Object.entries(resHeaders)) {
979
- if (name) {
980
- setHeader(name, value);
981
- if (opts?.debug) {
982
- console.log(`\t${''}${name}=${''}${value}${''}`);
983
- }
984
- }
985
- }
986
- }
987
- if (resCookies) {
988
- setHeadersObject['set-cookie'] = (setHeadersObject['set-cookie'] || []);
989
- for (const [name, value] of Object.entries(resCookies)) {
990
- if (name) {
991
- setHeadersObject['set-cookie'].push(`${name}=${value}`);
992
- if (opts?.debug) {
993
- console.log(`\t${''}${''}set-cookie=${''}${name}=${value}${''}`);
994
- }
995
- }
996
- }
997
- }
998
- return resp;
999
- };
1000
- }
1001
-
1002
- const httpStatusCodes = {
1003
- [100]: 'Continue',
1004
- [101]: 'Switching protocols',
1005
- [102]: 'Processing',
1006
- [103]: 'Early Hints',
1007
- [200]: 'OK',
1008
- [201]: 'Created',
1009
- [202]: 'Accepted',
1010
- [203]: 'Non-Authoritative Information',
1011
- [204]: 'No Content',
1012
- [205]: 'Reset Content',
1013
- [206]: 'Partial Content',
1014
- [207]: 'Multi-Status',
1015
- [208]: 'Already Reported',
1016
- [226]: 'IM Used',
1017
- [300]: 'Multiple Choices',
1018
- [301]: 'Moved Permanently',
1019
- [302]: 'Found (Previously "Moved Temporarily")',
1020
- [303]: 'See Other',
1021
- [304]: 'Not Modified',
1022
- [305]: 'Use Proxy',
1023
- [306]: 'Switch Proxy',
1024
- [307]: 'Temporary Redirect',
1025
- [308]: 'Permanent Redirect',
1026
- [400]: 'Bad Request',
1027
- [401]: 'Unauthorized',
1028
- [402]: 'Payment Required',
1029
- [403]: 'Forbidden',
1030
- [404]: 'Not Found',
1031
- [405]: 'Method Not Allowed',
1032
- [406]: 'Not Acceptable',
1033
- [407]: 'Proxy Authentication Required',
1034
- [408]: 'Request Timeout',
1035
- [409]: 'Conflict',
1036
- [410]: 'Gone',
1037
- [411]: 'Length Required',
1038
- [412]: 'Precondition Failed',
1039
- [413]: 'Payload Too Large',
1040
- [414]: 'URI Too Long',
1041
- [415]: 'Unsupported Media Type',
1042
- [416]: 'Range Not Satisfiable',
1043
- [417]: 'Expectation Failed',
1044
- [418]: 'I\'m a Teapot',
1045
- [421]: 'Misdirected Request',
1046
- [422]: 'Unprocessable Entity',
1047
- [423]: 'Locked',
1048
- [424]: 'Failed Dependency',
1049
- [425]: 'Too Early',
1050
- [426]: 'Upgrade Required',
1051
- [428]: 'Precondition Required',
1052
- [429]: 'Too Many Requests',
1053
- [431]: 'Request Header Fields Too Large',
1054
- [451]: 'Unavailable For Legal Reasons',
1055
- [500]: 'Internal Server Error',
1056
- [501]: 'Not Implemented',
1057
- [502]: 'Bad Gateway',
1058
- [503]: 'Service Unavailable',
1059
- [504]: 'Gateway Timeout',
1060
- [505]: 'HTTP Version Not Supported',
1061
- [506]: 'Variant Also Negotiates',
1062
- [507]: 'Insufficient Storage',
1063
- [508]: 'Loop Detected',
1064
- [510]: 'Not Extended',
1065
- [511]: 'Network Authentication Required',
1066
- };
1067
- exports.EHttpStatusCode = void 0;
1068
- (function (EHttpStatusCode) {
1069
- EHttpStatusCode[EHttpStatusCode["Continue"] = 100] = "Continue";
1070
- EHttpStatusCode[EHttpStatusCode["SwitchingProtocols"] = 101] = "SwitchingProtocols";
1071
- EHttpStatusCode[EHttpStatusCode["Processing"] = 102] = "Processing";
1072
- EHttpStatusCode[EHttpStatusCode["EarlyHints"] = 103] = "EarlyHints";
1073
- EHttpStatusCode[EHttpStatusCode["OK"] = 200] = "OK";
1074
- EHttpStatusCode[EHttpStatusCode["Created"] = 201] = "Created";
1075
- EHttpStatusCode[EHttpStatusCode["Accepted"] = 202] = "Accepted";
1076
- EHttpStatusCode[EHttpStatusCode["NonAuthoritativeInformation"] = 203] = "NonAuthoritativeInformation";
1077
- EHttpStatusCode[EHttpStatusCode["NoContent"] = 204] = "NoContent";
1078
- EHttpStatusCode[EHttpStatusCode["ResetContent"] = 205] = "ResetContent";
1079
- EHttpStatusCode[EHttpStatusCode["PartialContent"] = 206] = "PartialContent";
1080
- EHttpStatusCode[EHttpStatusCode["MultiStatus"] = 207] = "MultiStatus";
1081
- EHttpStatusCode[EHttpStatusCode["AlreadyReported"] = 208] = "AlreadyReported";
1082
- EHttpStatusCode[EHttpStatusCode["IMUsed"] = 226] = "IMUsed";
1083
- EHttpStatusCode[EHttpStatusCode["MultipleChoices"] = 300] = "MultipleChoices";
1084
- EHttpStatusCode[EHttpStatusCode["MovedPermanently"] = 301] = "MovedPermanently";
1085
- EHttpStatusCode[EHttpStatusCode["Found"] = 302] = "Found";
1086
- EHttpStatusCode[EHttpStatusCode["SeeOther"] = 303] = "SeeOther";
1087
- EHttpStatusCode[EHttpStatusCode["NotModified"] = 304] = "NotModified";
1088
- EHttpStatusCode[EHttpStatusCode["UseProxy"] = 305] = "UseProxy";
1089
- EHttpStatusCode[EHttpStatusCode["SwitchProxy"] = 306] = "SwitchProxy";
1090
- EHttpStatusCode[EHttpStatusCode["TemporaryRedirect"] = 307] = "TemporaryRedirect";
1091
- EHttpStatusCode[EHttpStatusCode["PermanentRedirect"] = 308] = "PermanentRedirect";
1092
- EHttpStatusCode[EHttpStatusCode["BadRequest"] = 400] = "BadRequest";
1093
- EHttpStatusCode[EHttpStatusCode["Unauthorized"] = 401] = "Unauthorized";
1094
- EHttpStatusCode[EHttpStatusCode["PaymentRequired"] = 402] = "PaymentRequired";
1095
- EHttpStatusCode[EHttpStatusCode["Forbidden"] = 403] = "Forbidden";
1096
- EHttpStatusCode[EHttpStatusCode["NotFound"] = 404] = "NotFound";
1097
- EHttpStatusCode[EHttpStatusCode["MethodNotAllowed"] = 405] = "MethodNotAllowed";
1098
- EHttpStatusCode[EHttpStatusCode["NotAcceptable"] = 406] = "NotAcceptable";
1099
- EHttpStatusCode[EHttpStatusCode["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired";
1100
- EHttpStatusCode[EHttpStatusCode["RequestTimeout"] = 408] = "RequestTimeout";
1101
- EHttpStatusCode[EHttpStatusCode["Conflict"] = 409] = "Conflict";
1102
- EHttpStatusCode[EHttpStatusCode["Gone"] = 410] = "Gone";
1103
- EHttpStatusCode[EHttpStatusCode["LengthRequired"] = 411] = "LengthRequired";
1104
- EHttpStatusCode[EHttpStatusCode["PreconditionFailed"] = 412] = "PreconditionFailed";
1105
- EHttpStatusCode[EHttpStatusCode["PayloadTooLarge"] = 413] = "PayloadTooLarge";
1106
- EHttpStatusCode[EHttpStatusCode["URITooLong"] = 414] = "URITooLong";
1107
- EHttpStatusCode[EHttpStatusCode["UnsupportedMediaType"] = 415] = "UnsupportedMediaType";
1108
- EHttpStatusCode[EHttpStatusCode["RangeNotSatisfiable"] = 416] = "RangeNotSatisfiable";
1109
- EHttpStatusCode[EHttpStatusCode["ExpectationFailed"] = 417] = "ExpectationFailed";
1110
- EHttpStatusCode[EHttpStatusCode["ImATeapot"] = 418] = "ImATeapot";
1111
- EHttpStatusCode[EHttpStatusCode["MisdirectedRequest"] = 421] = "MisdirectedRequest";
1112
- EHttpStatusCode[EHttpStatusCode["UnprocessableEntity"] = 422] = "UnprocessableEntity";
1113
- EHttpStatusCode[EHttpStatusCode["Locked"] = 423] = "Locked";
1114
- EHttpStatusCode[EHttpStatusCode["FailedDependency"] = 424] = "FailedDependency";
1115
- EHttpStatusCode[EHttpStatusCode["TooEarly"] = 425] = "TooEarly";
1116
- EHttpStatusCode[EHttpStatusCode["UpgradeRequired"] = 426] = "UpgradeRequired";
1117
- EHttpStatusCode[EHttpStatusCode["PreconditionRequired"] = 428] = "PreconditionRequired";
1118
- EHttpStatusCode[EHttpStatusCode["TooManyRequests"] = 429] = "TooManyRequests";
1119
- EHttpStatusCode[EHttpStatusCode["RequestHeaderFieldsTooLarge"] = 431] = "RequestHeaderFieldsTooLarge";
1120
- EHttpStatusCode[EHttpStatusCode["UnavailableForLegalReasons"] = 451] = "UnavailableForLegalReasons";
1121
- EHttpStatusCode[EHttpStatusCode["InternalServerError"] = 500] = "InternalServerError";
1122
- EHttpStatusCode[EHttpStatusCode["NotImplemented"] = 501] = "NotImplemented";
1123
- EHttpStatusCode[EHttpStatusCode["BadGateway"] = 502] = "BadGateway";
1124
- EHttpStatusCode[EHttpStatusCode["ServiceUnavailable"] = 503] = "ServiceUnavailable";
1125
- EHttpStatusCode[EHttpStatusCode["GatewayTimeout"] = 504] = "GatewayTimeout";
1126
- EHttpStatusCode[EHttpStatusCode["HTTPVersionNotSupported"] = 505] = "HTTPVersionNotSupported";
1127
- EHttpStatusCode[EHttpStatusCode["VariantAlsoNegotiates"] = 506] = "VariantAlsoNegotiates";
1128
- EHttpStatusCode[EHttpStatusCode["InsufficientStorage"] = 507] = "InsufficientStorage";
1129
- EHttpStatusCode[EHttpStatusCode["LoopDetected"] = 508] = "LoopDetected";
1130
- EHttpStatusCode[EHttpStatusCode["NotExtended"] = 510] = "NotExtended";
1131
- EHttpStatusCode[EHttpStatusCode["NetworkAuthenticationRequired"] = 511] = "NetworkAuthenticationRequired";
1132
- })(exports.EHttpStatusCode || (exports.EHttpStatusCode = {}));
1133
-
1134
- const defaultStatus = {
1135
- GET: exports.EHttpStatusCode.OK,
1136
- POST: exports.EHttpStatusCode.Created,
1137
- PUT: exports.EHttpStatusCode.Created,
1138
- PATCH: exports.EHttpStatusCode.Accepted,
1139
- DELETE: exports.EHttpStatusCode.Accepted,
1140
- };
1141
- const baseRenderer = new BaseWooksResponseRenderer();
1142
- const FetchResponse = Response;
1143
- class BaseWooksResponse {
1144
- renderer;
1145
- constructor(renderer = baseRenderer) {
1146
- this.renderer = renderer;
1147
- }
1148
- _status = 0;
1149
- _body;
1150
- _headers = {};
1151
- get status() {
1152
- return this._status;
1153
- }
1154
- set status(value) {
1155
- this._status = value;
1156
- }
1157
- get body() {
1158
- return this._body;
1159
- }
1160
- set body(value) {
1161
- this._body = value;
1162
- }
1163
- setStatus(value) {
1164
- this.status = value;
1165
- return this;
1166
- }
1167
- setBody(value) {
1168
- this.body = value;
1169
- return this;
1170
- }
1171
- getContentType() {
1172
- return this._headers['content-type'];
1173
- }
1174
- setContentType(value) {
1175
- this._headers['content-type'] = value;
1176
- return this;
1177
- }
1178
- enableCors(origin = '*') {
1179
- this._headers['Access-Control-Allow-Origin'] = origin;
1180
- return this;
1181
- }
1182
- setCookie(name, value, attrs) {
1183
- const cookies = this._headers['set-cookie'] = (this._headers['set-cookie'] || []);
1184
- cookies.push(renderCookie(name, { value, attrs: attrs || {} }));
1185
- return this;
1186
- }
1187
- setCacheControl(data) {
1188
- this.setHeader('cache-control', renderCacheControl(data));
1189
- }
1190
- setCookieRaw(rawValue) {
1191
- const cookies = this._headers['set-cookie'] = (this._headers['set-cookie'] || []);
1192
- cookies.push(rawValue);
1193
- return this;
1194
- }
1195
- header(name, value) {
1196
- this._headers[name] = value;
1197
- return this;
1198
- }
1199
- setHeader(name, value) {
1200
- return this.header(name, value);
1201
- }
1202
- getHeader(name) {
1203
- return this._headers[name];
1204
- }
1205
- mergeHeaders() {
1206
- const { headers } = useSetHeaders();
1207
- const { cookies, removeCookie } = useSetCookies();
1208
- const newCookies = (this._headers['set-cookie'] || []);
1209
- for (const cookie of newCookies) {
1210
- removeCookie(cookie.slice(0, cookie.indexOf('=')));
1211
- }
1212
- this._headers = {
1213
- server: `Wooks v${"0.0.1-beta.5"}`,
1214
- ...headers,
1215
- ...this._headers,
1216
- };
1217
- const setCookie = [...newCookies, ...cookies()];
1218
- if (setCookie && setCookie.length) {
1219
- this._headers['set-cookie'] = setCookie;
1220
- }
1221
- return this;
1222
- }
1223
- mergeStatus(renderedBody) {
1224
- this.status = this.status || useResponse().status();
1225
- if (!this.status) {
1226
- const { method } = useRequest();
1227
- this.status = renderedBody ? defaultStatus[method] || exports.EHttpStatusCode.OK : exports.EHttpStatusCode.NoContent;
1228
- }
1229
- return this;
1230
- }
1231
- respond() {
1232
- const { rawResponse, hasResponded } = useResponse();
1233
- const { method, rawRequest } = useRequest();
1234
- if (hasResponded()) {
1235
- throw panic('The response was already sent.');
1236
- }
1237
- this.mergeHeaders();
1238
- const res = rawResponse();
1239
- if (this.body instanceof stream.Readable) {
1240
- const stream = this.body;
1241
- this.mergeStatus('ok');
1242
- res.writeHead(this.status, {
1243
- ...this._headers,
1244
- });
1245
- rawRequest.once('close', () => {
1246
- stream.destroy();
1247
- });
1248
- if (method === 'HEAD') {
1249
- stream.destroy();
1250
- res.end();
1251
- }
1252
- else {
1253
- stream.on('error', () => {
1254
- stream.destroy();
1255
- res.end();
1256
- });
1257
- stream.on('close', () => {
1258
- stream.destroy();
1259
- });
1260
- stream.pipe(res);
1261
- }
1262
- }
1263
- else if (this.body instanceof FetchResponse) {
1264
- this.mergeStatus('ok');
1265
- if (method === 'HEAD') {
1266
- res.end();
1267
- }
1268
- else {
1269
- void respondWithFetch(this.body.body, res);
1270
- }
1271
- }
1272
- else {
1273
- const renderedBody = this.renderer.render(this);
1274
- this.mergeStatus(renderedBody);
1275
- res.writeHead(this.status, {
1276
- 'content-length': Buffer.byteLength(renderedBody),
1277
- ...this._headers,
1278
- }).end(method !== 'HEAD' ? renderedBody : '');
1279
- }
1280
- }
1281
- }
1282
- async function respondWithFetch(fetchBody, res) {
1283
- if (fetchBody) {
1284
- try {
1285
- for await (const chunk of fetchBody) {
1286
- res.write(chunk);
1287
- }
1288
- }
1289
- catch (e) {
1290
- }
1291
- }
1292
- res.end();
1293
- }
1294
-
1295
- const preStyles = 'font-family: monospace;'
1296
- + 'width: 100%;'
1297
- + 'max-width: 900px;'
1298
- + 'padding: 10px;'
1299
- + 'margin: 20px auto;'
1300
- + 'border-radius: 8px;'
1301
- + 'background-color: #494949;'
1302
- + 'box-shadow: 0px 0px 3px 2px rgb(255 255 255 / 20%);';
1303
- class WooksErrorRenderer extends BaseWooksResponseRenderer {
1304
- renderHtml(response) {
1305
- const data = response.body || {};
1306
- response.setContentType(contentTypes.text.html);
1307
- const keys = Object.keys(data).filter(key => !['statusCode', 'error', 'message'].includes(key));
1308
- return '<html style="background-color: #333; color: #bbb;">' +
1309
- `<head><title>${data.statusCode} ${httpStatusCodes[data.statusCode]}</title></head>` +
1310
- `<body><center><h1>${data.statusCode} ${httpStatusCodes[data.statusCode]}</h1></center>` +
1311
- `<center><h4>${data.message}</h1></center><hr color="#666">` +
1312
- `<center style="color: #666;"> Wooks v${"0.0.1-beta.5"} </center>` +
1313
- `${keys.length ? `<pre style="${preStyles}">${JSON.stringify({ ...data, statusCode: undefined, message: undefined, error: undefined }, null, ' ')}</pre>` : ''}` +
1314
- '</body></html>';
1315
- }
1316
- renderText(response) {
1317
- const data = response.body || {};
1318
- response.setContentType(contentTypes.text.plain);
1319
- const keys = Object.keys(data).filter(key => !['statusCode', 'error', 'message'].includes(key));
1320
- return `${data.statusCode} ${httpStatusCodes[data.statusCode]}\n${data.message}`
1321
- + `\n\n${keys.length ? `${JSON.stringify({ ...data, statusCode: undefined, message: undefined, error: undefined }, null, ' ')}` : ''}`;
1322
- }
1323
- renderJson(response) {
1324
- const data = response.body || {};
1325
- response.setContentType(contentTypes.application.json);
1326
- const keys = Object.keys(data).filter(key => !['statusCode', 'error', 'message'].includes(key));
1327
- return `{"statusCode":${escapeQuotes(data.statusCode)},`
1328
- + `"error":"${escapeQuotes(data.error)}",`
1329
- + `"message":"${escapeQuotes(data.message)}"`
1330
- + `${keys.length ? (',' + keys.map(k => `"${escapeQuotes(k)}":${JSON.stringify(data[k])}`).join(',')) : ''}}`;
1331
- }
1332
- render(response) {
1333
- const { acceptsJson, acceptsText, acceptsHtml } = useAccept();
1334
- response.status = response.body?.statusCode || 500;
1335
- if (acceptsJson()) {
1336
- return this.renderJson(response);
1337
- }
1338
- else if (acceptsHtml()) {
1339
- return this.renderHtml(response);
1340
- }
1341
- else if (acceptsText()) {
1342
- return this.renderText(response);
1343
- }
1344
- else {
1345
- return this.renderJson(response);
1346
- }
1347
- }
1348
- }
1349
- function escapeQuotes(s) {
1350
- return (typeof s === 'number' ? s : (s || '')).toString().replace(/[\""]/g, '\\"');
1351
- }
24
+ const banner = () => `[wooks][${new Date().toISOString().replace('T', ' ').replace(/\.\d{3}z$/i, '')}] `;
1352
25
 
1353
- class WooksError extends Error {
1354
- code;
1355
- _body;
1356
- constructor(code = 500, _body = '') {
1357
- super(typeof _body === 'string' ? _body : _body.message);
1358
- this.code = code;
1359
- this._body = _body;
1360
- }
1361
- get body() {
1362
- return typeof this._body === 'string' ? {
1363
- statusCode: this.code,
1364
- message: this.message,
1365
- error: httpStatusCodes[this.code],
1366
- } : {
1367
- ...this._body,
1368
- statusCode: this.code,
1369
- message: this.message,
1370
- error: httpStatusCodes[this.code],
1371
- };
1372
- }
1373
- renderer;
1374
- attachRenderer(renderer) {
1375
- this.renderer = renderer;
1376
- }
1377
- getRenderer() {
1378
- return this.renderer;
1379
- }
26
+ function logError(error) {
27
+ console.error('' + '' + banner() + error + '');
1380
28
  }
1381
29
 
1382
- function createResponseFrom(data) {
1383
- const { hasResponded } = useResponse();
1384
- if (hasResponded())
1385
- return null;
1386
- if (data instanceof Error) {
1387
- const r = new BaseWooksResponse(new WooksErrorRenderer());
1388
- let httpError;
1389
- if (data instanceof WooksError) {
1390
- httpError = data;
1391
- }
1392
- else {
1393
- httpError = new WooksError(500, data.message);
1394
- }
1395
- r.setBody(httpError.body);
1396
- return r;
1397
- }
1398
- else if (data instanceof BaseWooksResponse) {
1399
- return data;
1400
- }
1401
- else {
1402
- return new BaseWooksResponse().setBody(data);
1403
- }
30
+ function panic(error) {
31
+ logError(error);
32
+ return new Error(error);
1404
33
  }
1405
34
 
1406
35
  class Wooks {
1407
36
  options;
1408
37
  router;
1409
38
  server;
39
+ responder = composables.createWooksResponder();
1410
40
  _uncoughtExceptionHandler;
1411
41
  constructor(options) {
1412
42
  this.options = options;
@@ -1452,60 +82,56 @@ class Wooks {
1452
82
  }
1453
83
  processRequest(req, res) {
1454
84
  const found = this.router.lookup(req.method, req.url);
1455
- const ctx = {
1456
- __setHeader: {
1457
- Server: 'wooks v' + "0.0.1-beta.5",
1458
- },
1459
- };
85
+ const params = found?.ctx?.params || {};
86
+ const [restoreCtx, clearCtx] = composables.createWooksCtx({ req, res, params });
1460
87
  if (found) {
1461
- const params = found.ctx.params;
1462
- setCurrentWooksContext(req, res, params, ctx);
1463
- const { restoreCtx } = useCurrentWooksContext();
1464
88
  this.processHandlers(req, res, found)
1465
89
  .catch((e) => {
1466
90
  this.printError('Internal error, please report: ', e);
1467
91
  restoreCtx();
1468
- createResponseFrom(e)?.respond();
1469
- clearCurrentWooksContext();
92
+ this.respond(e);
93
+ clearCtx();
1470
94
  console.error('' + '' + banner(), e, '');
1471
95
  });
1472
96
  }
1473
97
  else {
1474
- setCurrentWooksContext(req, res, {}, ctx);
1475
- createResponseFrom(new WooksError(404))?.respond();
1476
- clearCurrentWooksContext();
98
+ this.respond(new composables.WooksError(404));
99
+ clearCtx();
1477
100
  }
1478
101
  }
1479
102
  async processHandlers(req, res, found) {
1480
- const { restoreCtx } = useCurrentWooksContext();
103
+ const { restoreCtx, clearCtx } = composables.useWooksCtx();
1481
104
  for (const [i, handler] of found.route.handlers.entries()) {
1482
105
  const isLastHandler = found.route.handlers.length === i + 1;
1483
106
  try {
1484
107
  restoreCtx();
1485
108
  const promise = handler();
1486
- clearCurrentWooksContext();
109
+ clearCtx();
1487
110
  const result = await promise;
1488
111
  restoreCtx();
1489
- createResponseFrom(result)?.respond();
1490
- clearCurrentWooksContext();
112
+ this.respond(result);
113
+ clearCtx();
1491
114
  break;
1492
115
  }
1493
116
  catch (e) {
1494
117
  this.printError('Uncought route handler exception: ' + (req.url || '') + '\n', e);
1495
118
  if (isLastHandler) {
1496
119
  restoreCtx();
1497
- createResponseFrom(e)?.respond();
1498
- clearCurrentWooksContext();
120
+ this.respond(e);
121
+ clearCtx();
1499
122
  }
1500
123
  }
1501
124
  }
1502
125
  }
1503
126
  printError(expl, e) {
1504
- if (!(e instanceof WooksError)) {
127
+ if (!(e instanceof composables.WooksError)) {
1505
128
  panic(expl + e.message);
1506
129
  console.error('' + (e.stack || '') + '');
1507
130
  }
1508
131
  }
132
+ respond(data) {
133
+ this.responder.respond(data);
134
+ }
1509
135
  get(path, handler) {
1510
136
  this.router.on('HEAD', path, handler);
1511
137
  return this.router.on('GET', path, handler);
@@ -1527,1372 +153,4 @@ class Wooks {
1527
153
  }
1528
154
  }
1529
155
 
1530
- const extensions = {
1531
- '123': 'application/vnd.lotus-1-2-3',
1532
- 'ez': 'application/andrew-inset',
1533
- 'aw': 'application/applixware',
1534
- 'atom': 'application/atom+xml',
1535
- 'atomcat': 'application/atomcat+xml',
1536
- 'atomdeleted': 'application/atomdeleted+xml',
1537
- 'atomsvc': 'application/atomsvc+xml',
1538
- 'dwd': 'application/atsc-dwd+xml',
1539
- 'held': 'application/atsc-held+xml',
1540
- 'rsat': 'application/atsc-rsat+xml',
1541
- 'bdoc': 'application/x-bdoc',
1542
- 'xcs': 'application/calendar+xml',
1543
- 'ccxml': 'application/ccxml+xml',
1544
- 'cdfx': 'application/cdfx+xml',
1545
- 'cdmia': 'application/cdmi-capability',
1546
- 'cdmic': 'application/cdmi-container',
1547
- 'cdmid': 'application/cdmi-domain',
1548
- 'cdmio': 'application/cdmi-object',
1549
- 'cdmiq': 'application/cdmi-queue',
1550
- 'cpl': 'application/cpl+xml',
1551
- 'cu': 'application/cu-seeme',
1552
- 'cwl': 'application/cwl',
1553
- 'mpd': 'application/dash+xml',
1554
- 'mpp': 'application/vnd.ms-project',
1555
- 'davmount': 'application/davmount+xml',
1556
- 'dbk': 'application/docbook+xml',
1557
- 'dssc': 'application/dssc+der',
1558
- 'xdssc': 'application/dssc+xml',
1559
- 'ecma': 'application/ecmascript',
1560
- 'emma': 'application/emma+xml',
1561
- 'emotionml': 'application/emotionml+xml',
1562
- 'epub': 'application/epub+zip',
1563
- 'exi': 'application/exi',
1564
- 'exp': 'application/express',
1565
- 'fdf': 'application/vnd.fdf',
1566
- 'fdt': 'application/fdt+xml',
1567
- 'pfr': 'application/font-tdpfr',
1568
- 'geojson': 'application/geo+json',
1569
- 'gml': 'application/gml+xml',
1570
- 'gpx': 'application/gpx+xml',
1571
- 'gxf': 'application/gxf',
1572
- 'gz': 'application/gzip',
1573
- 'hjson': 'application/hjson',
1574
- 'stk': 'application/hyperstudio',
1575
- 'ink': 'application/inkml+xml',
1576
- 'inkml': 'application/inkml+xml',
1577
- 'ipfix': 'application/ipfix',
1578
- 'its': 'application/its+xml',
1579
- 'jar': 'application/java-archive',
1580
- 'war': 'application/java-archive',
1581
- 'ear': 'application/java-archive',
1582
- 'ser': 'application/java-serialized-object',
1583
- 'class': 'application/java-vm',
1584
- 'js': 'application/javascript',
1585
- 'mjs': 'application/javascript',
1586
- 'json': 'application/json',
1587
- 'map': 'application/json',
1588
- 'json5': 'application/json5',
1589
- 'jsonml': 'application/jsonml+json',
1590
- 'jsonld': 'application/ld+json',
1591
- 'lgr': 'application/lgr+xml',
1592
- 'lostxml': 'application/lost+xml',
1593
- 'hqx': 'application/mac-binhex40',
1594
- 'cpt': 'application/mac-compactpro',
1595
- 'mads': 'application/mads+xml',
1596
- 'webmanifest': 'application/manifest+json',
1597
- 'mrc': 'application/marc',
1598
- 'mrcx': 'application/marcxml+xml',
1599
- 'ma': 'application/mathematica',
1600
- 'nb': 'application/mathematica',
1601
- 'mb': 'application/mathematica',
1602
- 'mathml': 'application/mathml+xml',
1603
- 'mbox': 'application/mbox',
1604
- 'mpf': 'application/media-policy-dataset+xml',
1605
- 'mscml': 'application/mediaservercontrol+xml',
1606
- 'metalink': 'application/metalink+xml',
1607
- 'meta4': 'application/metalink4+xml',
1608
- 'mets': 'application/mets+xml',
1609
- 'maei': 'application/mmt-aei+xml',
1610
- 'musd': 'application/mmt-usd+xml',
1611
- 'mods': 'application/mods+xml',
1612
- 'm21': 'application/mp21',
1613
- 'mp21': 'application/mp21',
1614
- 'mp4s': 'application/mp4',
1615
- 'm4p': 'application/mp4',
1616
- 'doc': 'application/msword',
1617
- 'dot': 'application/msword',
1618
- 'mxf': 'application/mxf',
1619
- 'nq': 'application/n-quads',
1620
- 'nt': 'application/n-triples',
1621
- 'cjs': 'application/node',
1622
- 'bin': 'application/octet-stream',
1623
- 'dms': 'application/octet-stream',
1624
- 'lrf': 'application/octet-stream',
1625
- 'mar': 'application/octet-stream',
1626
- 'so': 'application/octet-stream',
1627
- 'dist': 'application/octet-stream',
1628
- 'distz': 'application/octet-stream',
1629
- 'pkg': 'application/octet-stream',
1630
- 'bpk': 'application/octet-stream',
1631
- 'dump': 'application/octet-stream',
1632
- 'elc': 'application/octet-stream',
1633
- 'deploy': 'application/octet-stream',
1634
- 'exe': 'application/x-msdownload',
1635
- 'dll': 'application/x-msdownload',
1636
- 'deb': 'application/x-debian-package',
1637
- 'dmg': 'application/x-apple-diskimage',
1638
- 'iso': 'application/x-iso9660-image',
1639
- 'img': 'application/octet-stream',
1640
- 'msi': 'application/x-msdownload',
1641
- 'msp': 'application/octet-stream',
1642
- 'msm': 'application/octet-stream',
1643
- 'buffer': 'application/octet-stream',
1644
- 'oda': 'application/oda',
1645
- 'opf': 'application/oebps-package+xml',
1646
- 'ogx': 'application/ogg',
1647
- 'omdoc': 'application/omdoc+xml',
1648
- 'onetoc': 'application/onenote',
1649
- 'onetoc2': 'application/onenote',
1650
- 'onetmp': 'application/onenote',
1651
- 'onepkg': 'application/onenote',
1652
- 'oxps': 'application/oxps',
1653
- 'relo': 'application/p2p-overlay+xml',
1654
- 'xer': 'application/patch-ops-error+xml',
1655
- 'pdf': 'application/pdf',
1656
- 'pgp': 'application/pgp-encrypted',
1657
- 'asc': 'application/pgp-signature',
1658
- 'sig': 'application/pgp-signature',
1659
- 'prf': 'application/pics-rules',
1660
- 'p10': 'application/pkcs10',
1661
- 'p7m': 'application/pkcs7-mime',
1662
- 'p7c': 'application/pkcs7-mime',
1663
- 'p7s': 'application/pkcs7-signature',
1664
- 'p8': 'application/pkcs8',
1665
- 'ac': 'application/vnd.nokia.n-gage.ac+xml',
1666
- 'cer': 'application/pkix-cert',
1667
- 'crl': 'application/pkix-crl',
1668
- 'pkipath': 'application/pkix-pkipath',
1669
- 'pki': 'application/pkixcmp',
1670
- 'pls': 'application/pls+xml',
1671
- 'ai': 'application/postscript',
1672
- 'eps': 'application/postscript',
1673
- 'ps': 'application/postscript',
1674
- 'provx': 'application/provenance+xml',
1675
- 'cww': 'application/prs.cww',
1676
- 'pskcxml': 'application/pskc+xml',
1677
- 'raml': 'application/raml+yaml',
1678
- 'rdf': 'application/rdf+xml',
1679
- 'owl': 'application/rdf+xml',
1680
- 'rif': 'application/reginfo+xml',
1681
- 'rnc': 'application/relax-ng-compact-syntax',
1682
- 'rl': 'application/resource-lists+xml',
1683
- 'rld': 'application/resource-lists-diff+xml',
1684
- 'rs': 'application/rls-services+xml',
1685
- 'rapd': 'application/route-apd+xml',
1686
- 'sls': 'application/route-s-tsid+xml',
1687
- 'rusd': 'application/route-usd+xml',
1688
- 'gbr': 'application/rpki-ghostbusters',
1689
- 'mft': 'application/rpki-manifest',
1690
- 'roa': 'application/rpki-roa',
1691
- 'rsd': 'application/rsd+xml',
1692
- 'rss': 'application/rss+xml',
1693
- 'rtf': 'text/rtf',
1694
- 'sbml': 'application/sbml+xml',
1695
- 'scq': 'application/scvp-cv-request',
1696
- 'scs': 'application/scvp-cv-response',
1697
- 'spq': 'application/scvp-vp-request',
1698
- 'spp': 'application/scvp-vp-response',
1699
- 'sdp': 'application/sdp',
1700
- 'senmlx': 'application/senml+xml',
1701
- 'sensmlx': 'application/sensml+xml',
1702
- 'setpay': 'application/set-payment-initiation',
1703
- 'setreg': 'application/set-registration-initiation',
1704
- 'shf': 'application/shf+xml',
1705
- 'siv': 'application/sieve',
1706
- 'sieve': 'application/sieve',
1707
- 'smi': 'application/smil+xml',
1708
- 'smil': 'application/smil+xml',
1709
- 'rq': 'application/sparql-query',
1710
- 'srx': 'application/sparql-results+xml',
1711
- 'gram': 'application/srgs',
1712
- 'grxml': 'application/srgs+xml',
1713
- 'sru': 'application/sru+xml',
1714
- 'ssdl': 'application/ssdl+xml',
1715
- 'ssml': 'application/ssml+xml',
1716
- 'swidtag': 'application/swid+xml',
1717
- 'tei': 'application/tei+xml',
1718
- 'teicorpus': 'application/tei+xml',
1719
- 'tfi': 'application/thraud+xml',
1720
- 'tsd': 'application/timestamped-data',
1721
- 'toml': 'application/toml',
1722
- 'trig': 'application/trig',
1723
- 'ttml': 'application/ttml+xml',
1724
- 'ubj': 'application/ubjson',
1725
- 'rsheet': 'application/urc-ressheet+xml',
1726
- 'td': 'application/urc-targetdesc+xml',
1727
- '1km': 'application/vnd.1000minds.decision-model+xml',
1728
- 'plb': 'application/vnd.3gpp.pic-bw-large',
1729
- 'psb': 'application/vnd.3gpp.pic-bw-small',
1730
- 'pvb': 'application/vnd.3gpp.pic-bw-var',
1731
- 'tcap': 'application/vnd.3gpp2.tcap',
1732
- 'pwn': 'application/vnd.3m.post-it-notes',
1733
- 'aso': 'application/vnd.accpac.simply.aso',
1734
- 'imp': 'application/vnd.accpac.simply.imp',
1735
- 'acu': 'application/vnd.acucobol',
1736
- 'atc': 'application/vnd.acucorp',
1737
- 'acutc': 'application/vnd.acucorp',
1738
- 'air': 'application/vnd.adobe.air-application-installer-package+zip',
1739
- 'fcdt': 'application/vnd.adobe.formscentral.fcdt',
1740
- 'fxp': 'application/vnd.adobe.fxp',
1741
- 'fxpl': 'application/vnd.adobe.fxp',
1742
- 'xdp': 'application/vnd.adobe.xdp+xml',
1743
- 'xfdf': 'application/xfdf',
1744
- 'age': 'application/vnd.age',
1745
- 'ahead': 'application/vnd.ahead.space',
1746
- 'azf': 'application/vnd.airzip.filesecure.azf',
1747
- 'azs': 'application/vnd.airzip.filesecure.azs',
1748
- 'azw': 'application/vnd.amazon.ebook',
1749
- 'acc': 'application/vnd.americandynamics.acc',
1750
- 'ami': 'application/vnd.amiga.ami',
1751
- 'apk': 'application/vnd.android.package-archive',
1752
- 'cii': 'application/vnd.anser-web-certificate-issue-initiation',
1753
- 'fti': 'application/vnd.anser-web-funds-transfer-initiation',
1754
- 'atx': 'application/vnd.antix.game-component',
1755
- 'mpkg': 'application/vnd.apple.installer+xml',
1756
- 'key': 'application/x-iwork-keynote-sffkey',
1757
- 'm3u8': 'application/vnd.apple.mpegurl',
1758
- 'numbers': 'application/x-iwork-numbers-sffnumbers',
1759
- 'pages': 'application/x-iwork-pages-sffpages',
1760
- 'pkpass': 'application/vnd.apple.pkpass',
1761
- 'swi': 'application/vnd.aristanetworks.swi',
1762
- 'iota': 'application/vnd.astraea-software.iota',
1763
- 'aep': 'application/vnd.audiograph',
1764
- 'bmml': 'application/vnd.balsamiq.bmml+xml',
1765
- 'mpm': 'application/vnd.blueice.multipass',
1766
- 'bmi': 'application/vnd.bmi',
1767
- 'rep': 'application/vnd.businessobjects',
1768
- 'cdxml': 'application/vnd.chemdraw+xml',
1769
- 'mmd': 'application/vnd.chipnuts.karaoke-mmd',
1770
- 'cdy': 'application/vnd.cinderella',
1771
- 'csl': 'application/vnd.citationstyles.style+xml',
1772
- 'cla': 'application/vnd.claymore',
1773
- 'rp9': 'application/vnd.cloanto.rp9',
1774
- 'c4g': 'application/vnd.clonk.c4group',
1775
- 'c4d': 'application/vnd.clonk.c4group',
1776
- 'c4f': 'application/vnd.clonk.c4group',
1777
- 'c4p': 'application/vnd.clonk.c4group',
1778
- 'c4u': 'application/vnd.clonk.c4group',
1779
- 'c11amc': 'application/vnd.cluetrust.cartomobile-config',
1780
- 'c11amz': 'application/vnd.cluetrust.cartomobile-config-pkg',
1781
- 'csp': 'application/vnd.commonspace',
1782
- 'cdbcmsg': 'application/vnd.contact.cmsg',
1783
- 'cmc': 'application/vnd.cosmocaller',
1784
- 'clkx': 'application/vnd.crick.clicker',
1785
- 'clkk': 'application/vnd.crick.clicker.keyboard',
1786
- 'clkp': 'application/vnd.crick.clicker.palette',
1787
- 'clkt': 'application/vnd.crick.clicker.template',
1788
- 'clkw': 'application/vnd.crick.clicker.wordbank',
1789
- 'wbs': 'application/vnd.criticaltools.wbs+xml',
1790
- 'pml': 'application/vnd.ctc-posml',
1791
- 'ppd': 'application/vnd.cups-ppd',
1792
- 'car': 'application/vnd.curl.car',
1793
- 'pcurl': 'application/vnd.curl.pcurl',
1794
- 'dart': 'application/vnd.dart',
1795
- 'rdz': 'application/vnd.data-vision.rdz',
1796
- 'dbf': 'application/vnd.dbf',
1797
- 'uvf': 'application/vnd.dece.data',
1798
- 'uvvf': 'application/vnd.dece.data',
1799
- 'uvd': 'application/vnd.dece.data',
1800
- 'uvvd': 'application/vnd.dece.data',
1801
- 'uvt': 'application/vnd.dece.ttml+xml',
1802
- 'uvvt': 'application/vnd.dece.ttml+xml',
1803
- 'uvx': 'application/vnd.dece.unspecified',
1804
- 'uvvx': 'application/vnd.dece.unspecified',
1805
- 'uvz': 'application/vnd.dece.zip',
1806
- 'uvvz': 'application/vnd.dece.zip',
1807
- 'fe_launch': 'application/vnd.denovo.fcselayout-link',
1808
- 'dna': 'application/vnd.dna',
1809
- 'mlp': 'application/vnd.dolby.mlp',
1810
- 'dpg': 'application/vnd.dpgraph',
1811
- 'dfac': 'application/vnd.dreamfactory',
1812
- 'kpxx': 'application/vnd.ds-keypoint',
1813
- 'ait': 'application/vnd.dvb.ait',
1814
- 'svc': 'application/vnd.dvb.service',
1815
- 'geo': 'application/vnd.dynageo',
1816
- 'mag': 'application/vnd.ecowin.chart',
1817
- 'nml': 'application/vnd.enliven',
1818
- 'esf': 'application/vnd.epson.esf',
1819
- 'msf': 'application/vnd.epson.msf',
1820
- 'qam': 'application/vnd.epson.quickanime',
1821
- 'slt': 'application/vnd.epson.salt',
1822
- 'ssf': 'application/vnd.epson.ssf',
1823
- 'es3': 'application/vnd.eszigno3+xml',
1824
- 'et3': 'application/vnd.eszigno3+xml',
1825
- 'ez2': 'application/vnd.ezpix-album',
1826
- 'ez3': 'application/vnd.ezpix-package',
1827
- 'mseed': 'application/vnd.fdsn.mseed',
1828
- 'seed': 'application/vnd.fdsn.seed',
1829
- 'dataless': 'application/vnd.fdsn.seed',
1830
- 'gph': 'application/vnd.flographit',
1831
- 'ftc': 'application/vnd.fluxtime.clip',
1832
- 'fm': 'application/vnd.framemaker',
1833
- 'frame': 'application/vnd.framemaker',
1834
- 'maker': 'application/vnd.framemaker',
1835
- 'book': 'application/vnd.framemaker',
1836
- 'fnc': 'application/vnd.frogans.fnc',
1837
- 'ltf': 'application/vnd.frogans.ltf',
1838
- 'fsc': 'application/vnd.fsc.weblaunch',
1839
- 'oas': 'application/vnd.fujitsu.oasys',
1840
- 'oa2': 'application/vnd.fujitsu.oasys2',
1841
- 'oa3': 'application/vnd.fujitsu.oasys3',
1842
- 'fg5': 'application/vnd.fujitsu.oasysgp',
1843
- 'bh2': 'application/vnd.fujitsu.oasysprs',
1844
- 'ddd': 'application/vnd.fujixerox.ddd',
1845
- 'xdw': 'application/vnd.fujixerox.docuworks',
1846
- 'xbd': 'application/vnd.fujixerox.docuworks.binder',
1847
- 'fzs': 'application/vnd.fuzzysheet',
1848
- 'txd': 'application/vnd.genomatix.tuxedo',
1849
- 'ggb': 'application/vnd.geogebra.file',
1850
- 'ggt': 'application/vnd.geogebra.tool',
1851
- 'gex': 'application/vnd.geometry-explorer',
1852
- 'gre': 'application/vnd.geometry-explorer',
1853
- 'gxt': 'application/vnd.geonext',
1854
- 'g2w': 'application/vnd.geoplan',
1855
- 'g3w': 'application/vnd.geospace',
1856
- 'gmx': 'application/vnd.gmx',
1857
- 'gdoc': 'application/vnd.google-apps.document',
1858
- 'gslides': 'application/vnd.google-apps.presentation',
1859
- 'gsheet': 'application/vnd.google-apps.spreadsheet',
1860
- 'kml': 'application/vnd.google-earth.kml+xml',
1861
- 'kmz': 'application/vnd.google-earth.kmz',
1862
- 'gqf': 'application/vnd.grafeq',
1863
- 'gqs': 'application/vnd.grafeq',
1864
- 'gac': 'application/vnd.groove-account',
1865
- 'ghf': 'application/vnd.groove-help',
1866
- 'gim': 'application/vnd.groove-identity-message',
1867
- 'grv': 'application/vnd.groove-injector',
1868
- 'gtm': 'application/vnd.groove-tool-message',
1869
- 'tpl': 'application/vnd.groove-tool-template',
1870
- 'vcg': 'application/vnd.groove-vcard',
1871
- 'hal': 'application/vnd.hal+xml',
1872
- 'zmm': 'application/vnd.handheld-entertainment+xml',
1873
- 'hbci': 'application/vnd.hbci',
1874
- 'les': 'application/vnd.hhe.lesson-player',
1875
- 'hpgl': 'application/vnd.hp-hpgl',
1876
- 'hpid': 'application/vnd.hp-hpid',
1877
- 'hps': 'application/vnd.hp-hps',
1878
- 'jlt': 'application/vnd.hp-jlyt',
1879
- 'pcl': 'application/vnd.hp-pcl',
1880
- 'pclxl': 'application/vnd.hp-pclxl',
1881
- 'sfd-hdstx': 'application/vnd.hydrostatix.sof-data',
1882
- 'mpy': 'application/vnd.ibm.minipay',
1883
- 'afp': 'application/vnd.ibm.modcap',
1884
- 'listafp': 'application/vnd.ibm.modcap',
1885
- 'list3820': 'application/vnd.ibm.modcap',
1886
- 'irm': 'application/vnd.ibm.rights-management',
1887
- 'sc': 'application/vnd.ibm.secure-container',
1888
- 'icc': 'application/vnd.iccprofile',
1889
- 'icm': 'application/vnd.iccprofile',
1890
- 'igl': 'application/vnd.igloader',
1891
- 'ivp': 'application/vnd.immervision-ivp',
1892
- 'ivu': 'application/vnd.immervision-ivu',
1893
- 'igm': 'application/vnd.insors.igm',
1894
- 'xpw': 'application/vnd.intercon.formnet',
1895
- 'xpx': 'application/vnd.intercon.formnet',
1896
- 'i2g': 'application/vnd.intergeo',
1897
- 'qbo': 'application/vnd.intu.qbo',
1898
- 'qfx': 'application/vnd.intu.qfx',
1899
- 'rcprofile': 'application/vnd.ipunplugged.rcprofile',
1900
- 'irp': 'application/vnd.irepository.package+xml',
1901
- 'xpr': 'application/vnd.is-xpr',
1902
- 'fcs': 'application/vnd.isac.fcs',
1903
- 'jam': 'application/vnd.jam',
1904
- 'rms': 'application/vnd.jcp.javame.midlet-rms',
1905
- 'jisp': 'application/vnd.jisp',
1906
- 'joda': 'application/vnd.joost.joda-archive',
1907
- 'ktz': 'application/vnd.kahootz',
1908
- 'ktr': 'application/vnd.kahootz',
1909
- 'karbon': 'application/vnd.kde.karbon',
1910
- 'chrt': 'application/vnd.kde.kchart',
1911
- 'kfo': 'application/vnd.kde.kformula',
1912
- 'flw': 'application/vnd.kde.kivio',
1913
- 'kon': 'application/vnd.kde.kontour',
1914
- 'kpr': 'application/vnd.kde.kpresenter',
1915
- 'kpt': 'application/vnd.kde.kpresenter',
1916
- 'ksp': 'application/vnd.kde.kspread',
1917
- 'kwd': 'application/vnd.kde.kword',
1918
- 'kwt': 'application/vnd.kde.kword',
1919
- 'htke': 'application/vnd.kenameaapp',
1920
- 'kia': 'application/vnd.kidspiration',
1921
- 'kne': 'application/vnd.kinar',
1922
- 'knp': 'application/vnd.kinar',
1923
- 'skp': 'application/vnd.koan',
1924
- 'skd': 'application/vnd.koan',
1925
- 'skt': 'application/vnd.koan',
1926
- 'skm': 'application/vnd.koan',
1927
- 'sse': 'application/vnd.kodak-descriptor',
1928
- 'lasxml': 'application/vnd.las.las+xml',
1929
- 'lbd': 'application/vnd.llamagraphics.life-balance.desktop',
1930
- 'lbe': 'application/vnd.llamagraphics.life-balance.exchange+xml',
1931
- 'apr': 'application/vnd.lotus-approach',
1932
- 'pre': 'application/vnd.lotus-freelance',
1933
- 'nsf': 'application/vnd.lotus-notes',
1934
- 'org': 'text/x-org',
1935
- 'scm': 'application/vnd.lotus-screencam',
1936
- 'lwp': 'application/vnd.lotus-wordpro',
1937
- 'portpkg': 'application/vnd.macports.portpkg',
1938
- 'mvt': 'application/vnd.mapbox-vector-tile',
1939
- 'mcd': 'application/vnd.mcd',
1940
- 'mc1': 'application/vnd.medcalcdata',
1941
- 'cdkey': 'application/vnd.mediastation.cdkey',
1942
- 'mwf': 'application/vnd.mfer',
1943
- 'mfm': 'application/vnd.mfmp',
1944
- 'flo': 'application/vnd.micrografx.flo',
1945
- 'igx': 'application/vnd.micrografx.igx',
1946
- 'mif': 'application/vnd.mif',
1947
- 'daf': 'application/vnd.mobius.daf',
1948
- 'dis': 'application/vnd.mobius.dis',
1949
- 'mbk': 'application/vnd.mobius.mbk',
1950
- 'mqy': 'application/vnd.mobius.mqy',
1951
- 'msl': 'application/vnd.mobius.msl',
1952
- 'plc': 'application/vnd.mobius.plc',
1953
- 'txf': 'application/vnd.mobius.txf',
1954
- 'mpn': 'application/vnd.mophun.application',
1955
- 'mpc': 'application/vnd.mophun.certificate',
1956
- 'xul': 'application/vnd.mozilla.xul+xml',
1957
- 'cil': 'application/vnd.ms-artgalry',
1958
- 'cab': 'application/vnd.ms-cab-compressed',
1959
- 'xls': 'application/vnd.ms-excel',
1960
- 'xlm': 'application/vnd.ms-excel',
1961
- 'xla': 'application/vnd.ms-excel',
1962
- 'xlc': 'application/vnd.ms-excel',
1963
- 'xlt': 'application/vnd.ms-excel',
1964
- 'xlw': 'application/vnd.ms-excel',
1965
- 'xlam': 'application/vnd.ms-excel.addin.macroenabled.12',
1966
- 'xlsb': 'application/vnd.ms-excel.sheet.binary.macroenabled.12',
1967
- 'xlsm': 'application/vnd.ms-excel.sheet.macroenabled.12',
1968
- 'xltm': 'application/vnd.ms-excel.template.macroenabled.12',
1969
- 'eot': 'application/vnd.ms-fontobject',
1970
- 'chm': 'application/vnd.ms-htmlhelp',
1971
- 'ims': 'application/vnd.ms-ims',
1972
- 'lrm': 'application/vnd.ms-lrm',
1973
- 'thmx': 'application/vnd.ms-officetheme',
1974
- 'msg': 'application/vnd.ms-outlook',
1975
- 'cat': 'application/vnd.ms-pki.seccat',
1976
- 'stl': 'model/stl',
1977
- 'ppt': 'application/vnd.ms-powerpoint',
1978
- 'pps': 'application/vnd.ms-powerpoint',
1979
- 'pot': 'application/vnd.ms-powerpoint',
1980
- 'ppam': 'application/vnd.ms-powerpoint.addin.macroenabled.12',
1981
- 'pptm': 'application/vnd.ms-powerpoint.presentation.macroenabled.12',
1982
- 'sldm': 'application/vnd.ms-powerpoint.slide.macroenabled.12',
1983
- 'ppsm': 'application/vnd.ms-powerpoint.slideshow.macroenabled.12',
1984
- 'potm': 'application/vnd.ms-powerpoint.template.macroenabled.12',
1985
- 'mpt': 'application/vnd.ms-project',
1986
- 'docm': 'application/vnd.ms-word.document.macroenabled.12',
1987
- 'dotm': 'application/vnd.ms-word.template.macroenabled.12',
1988
- 'wps': 'application/vnd.ms-works',
1989
- 'wks': 'application/vnd.ms-works',
1990
- 'wcm': 'application/vnd.ms-works',
1991
- 'wdb': 'application/vnd.ms-works',
1992
- 'wpl': 'application/vnd.ms-wpl',
1993
- 'xps': 'application/vnd.ms-xpsdocument',
1994
- 'mseq': 'application/vnd.mseq',
1995
- 'mus': 'application/vnd.musician',
1996
- 'msty': 'application/vnd.muvee.style',
1997
- 'taglet': 'application/vnd.mynfc',
1998
- 'nlu': 'application/vnd.neurolanguage.nlu',
1999
- 'ntf': 'application/vnd.nitf',
2000
- 'nitf': 'application/vnd.nitf',
2001
- 'nnd': 'application/vnd.noblenet-directory',
2002
- 'nns': 'application/vnd.noblenet-sealer',
2003
- 'nnw': 'application/vnd.noblenet-web',
2004
- 'ngdat': 'application/vnd.nokia.n-gage.data',
2005
- 'n-gage': 'application/vnd.nokia.n-gage.symbian.install',
2006
- 'rpst': 'application/vnd.nokia.radio-preset',
2007
- 'rpss': 'application/vnd.nokia.radio-presets',
2008
- 'edm': 'application/vnd.novadigm.edm',
2009
- 'edx': 'application/vnd.novadigm.edx',
2010
- 'ext': 'application/vnd.novadigm.ext',
2011
- 'odc': 'application/vnd.oasis.opendocument.chart',
2012
- 'otc': 'application/vnd.oasis.opendocument.chart-template',
2013
- 'odb': 'application/vnd.oasis.opendocument.database',
2014
- 'odf': 'application/vnd.oasis.opendocument.formula',
2015
- 'odft': 'application/vnd.oasis.opendocument.formula-template',
2016
- 'odg': 'application/vnd.oasis.opendocument.graphics',
2017
- 'otg': 'application/vnd.oasis.opendocument.graphics-template',
2018
- 'odi': 'application/vnd.oasis.opendocument.image',
2019
- 'oti': 'application/vnd.oasis.opendocument.image-template',
2020
- 'odp': 'application/vnd.oasis.opendocument.presentation',
2021
- 'otp': 'application/vnd.oasis.opendocument.presentation-template',
2022
- 'ods': 'application/vnd.oasis.opendocument.spreadsheet',
2023
- 'ots': 'application/vnd.oasis.opendocument.spreadsheet-template',
2024
- 'odt': 'application/vnd.oasis.opendocument.text',
2025
- 'odm': 'application/vnd.oasis.opendocument.text-master',
2026
- 'ott': 'application/vnd.oasis.opendocument.text-template',
2027
- 'oth': 'application/vnd.oasis.opendocument.text-web',
2028
- 'xo': 'application/vnd.olpc-sugar',
2029
- 'dd2': 'application/vnd.oma.dd2+xml',
2030
- 'obgx': 'application/vnd.openblox.game+xml',
2031
- 'oxt': 'application/vnd.openofficeorg.extension',
2032
- 'osm': 'application/vnd.openstreetmap.data+xml',
2033
- 'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
2034
- 'sldx': 'application/vnd.openxmlformats-officedocument.presentationml.slide',
2035
- 'ppsx': 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
2036
- 'potx': 'application/vnd.openxmlformats-officedocument.presentationml.template',
2037
- 'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
2038
- 'xltx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
2039
- 'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
2040
- 'dotx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
2041
- 'mgp': 'application/vnd.osgeo.mapguide.package',
2042
- 'dp': 'application/vnd.osgi.dp',
2043
- 'esa': 'application/vnd.osgi.subsystem',
2044
- 'pdb': 'application/x-pilot',
2045
- 'pqa': 'application/vnd.palm',
2046
- 'oprc': 'application/vnd.palm',
2047
- 'paw': 'application/vnd.pawaafile',
2048
- 'str': 'application/vnd.pg.format',
2049
- 'ei6': 'application/vnd.pg.osasli',
2050
- 'efif': 'application/vnd.picsel',
2051
- 'wg': 'application/vnd.pmi.widget',
2052
- 'plf': 'application/vnd.pocketlearn',
2053
- 'pbd': 'application/vnd.powerbuilder6',
2054
- 'box': 'application/vnd.previewsystems.box',
2055
- 'mgz': 'application/vnd.proteus.magazine',
2056
- 'qps': 'application/vnd.publishare-delta-tree',
2057
- 'ptid': 'application/vnd.pvi.ptid1',
2058
- 'qxd': 'application/vnd.quark.quarkxpress',
2059
- 'qxt': 'application/vnd.quark.quarkxpress',
2060
- 'qwd': 'application/vnd.quark.quarkxpress',
2061
- 'qwt': 'application/vnd.quark.quarkxpress',
2062
- 'qxl': 'application/vnd.quark.quarkxpress',
2063
- 'qxb': 'application/vnd.quark.quarkxpress',
2064
- 'rar': 'application/x-rar-compressed',
2065
- 'bed': 'application/vnd.realvnc.bed',
2066
- 'mxl': 'application/vnd.recordare.musicxml',
2067
- 'musicxml': 'application/vnd.recordare.musicxml+xml',
2068
- 'cryptonote': 'application/vnd.rig.cryptonote',
2069
- 'cod': 'application/vnd.rim.cod',
2070
- 'rm': 'application/vnd.rn-realmedia',
2071
- 'rmvb': 'application/vnd.rn-realmedia-vbr',
2072
- 'link66': 'application/vnd.route66.link66+xml',
2073
- 'st': 'application/vnd.sailingtracker.track',
2074
- 'see': 'application/vnd.seemail',
2075
- 'sema': 'application/vnd.sema',
2076
- 'semd': 'application/vnd.semd',
2077
- 'semf': 'application/vnd.semf',
2078
- 'ifm': 'application/vnd.shana.informed.formdata',
2079
- 'itp': 'application/vnd.shana.informed.formtemplate',
2080
- 'iif': 'application/vnd.shana.informed.interchange',
2081
- 'ipk': 'application/vnd.shana.informed.package',
2082
- 'twd': 'application/vnd.simtech-mindmapper',
2083
- 'twds': 'application/vnd.simtech-mindmapper',
2084
- 'mmf': 'application/vnd.smaf',
2085
- 'teacher': 'application/vnd.smart.teacher',
2086
- 'fo': 'application/vnd.software602.filler.form+xml',
2087
- 'sdkm': 'application/vnd.solent.sdkm+xml',
2088
- 'sdkd': 'application/vnd.solent.sdkm+xml',
2089
- 'dxp': 'application/vnd.spotfire.dxp',
2090
- 'sfs': 'application/vnd.spotfire.sfs',
2091
- 'sdc': 'application/vnd.stardivision.calc',
2092
- 'sda': 'application/vnd.stardivision.draw',
2093
- 'sdd': 'application/vnd.stardivision.impress',
2094
- 'smf': 'application/vnd.stardivision.math',
2095
- 'sdw': 'application/vnd.stardivision.writer',
2096
- 'vor': 'application/vnd.stardivision.writer',
2097
- 'sgl': 'application/vnd.stardivision.writer-global',
2098
- 'smzip': 'application/vnd.stepmania.package',
2099
- 'sm': 'application/vnd.stepmania.stepchart',
2100
- 'wadl': 'application/vnd.sun.wadl+xml',
2101
- 'sxc': 'application/vnd.sun.xml.calc',
2102
- 'stc': 'application/vnd.sun.xml.calc.template',
2103
- 'sxd': 'application/vnd.sun.xml.draw',
2104
- 'std': 'application/vnd.sun.xml.draw.template',
2105
- 'sxi': 'application/vnd.sun.xml.impress',
2106
- 'sti': 'application/vnd.sun.xml.impress.template',
2107
- 'sxm': 'application/vnd.sun.xml.math',
2108
- 'sxw': 'application/vnd.sun.xml.writer',
2109
- 'sxg': 'application/vnd.sun.xml.writer.global',
2110
- 'stw': 'application/vnd.sun.xml.writer.template',
2111
- 'sus': 'application/vnd.sus-calendar',
2112
- 'susp': 'application/vnd.sus-calendar',
2113
- 'svd': 'application/vnd.svd',
2114
- 'sis': 'application/vnd.symbian.install',
2115
- 'sisx': 'application/vnd.symbian.install',
2116
- 'xsm': 'application/vnd.syncml+xml',
2117
- 'bdm': 'application/vnd.syncml.dm+wbxml',
2118
- 'xdm': 'application/vnd.syncml.dm+xml',
2119
- 'ddf': 'application/vnd.syncml.dmddf+xml',
2120
- 'tao': 'application/vnd.tao.intent-module-archive',
2121
- 'pcap': 'application/vnd.tcpdump.pcap',
2122
- 'cap': 'application/vnd.tcpdump.pcap',
2123
- 'dmp': 'application/vnd.tcpdump.pcap',
2124
- 'tmo': 'application/vnd.tmobile-livetv',
2125
- 'tpt': 'application/vnd.trid.tpt',
2126
- 'mxs': 'application/vnd.triscape.mxs',
2127
- 'tra': 'application/vnd.trueapp',
2128
- 'ufd': 'application/vnd.ufdl',
2129
- 'ufdl': 'application/vnd.ufdl',
2130
- 'utz': 'application/vnd.uiq.theme',
2131
- 'umj': 'application/vnd.umajin',
2132
- 'unityweb': 'application/vnd.unity',
2133
- 'uoml': 'application/vnd.uoml+xml',
2134
- 'vcx': 'application/vnd.vcx',
2135
- 'vsd': 'application/vnd.visio',
2136
- 'vst': 'application/vnd.visio',
2137
- 'vss': 'application/vnd.visio',
2138
- 'vsw': 'application/vnd.visio',
2139
- 'vis': 'application/vnd.visionary',
2140
- 'vsf': 'application/vnd.vsf',
2141
- 'wbxml': 'application/vnd.wap.wbxml',
2142
- 'wmlc': 'application/vnd.wap.wmlc',
2143
- 'wmlsc': 'application/vnd.wap.wmlscriptc',
2144
- 'wtb': 'application/vnd.webturbo',
2145
- 'nbp': 'application/vnd.wolfram.player',
2146
- 'wpd': 'application/vnd.wordperfect',
2147
- 'wqd': 'application/vnd.wqd',
2148
- 'stf': 'application/vnd.wt.stf',
2149
- 'xar': 'application/vnd.xara',
2150
- 'xfdl': 'application/vnd.xfdl',
2151
- 'hvd': 'application/vnd.yamaha.hv-dic',
2152
- 'hvs': 'application/vnd.yamaha.hv-script',
2153
- 'hvp': 'application/vnd.yamaha.hv-voice',
2154
- 'osf': 'application/vnd.yamaha.openscoreformat',
2155
- 'osfpvg': 'application/vnd.yamaha.openscoreformat.osfpvg+xml',
2156
- 'saf': 'application/vnd.yamaha.smaf-audio',
2157
- 'spf': 'application/vnd.yamaha.smaf-phrase',
2158
- 'cmp': 'application/vnd.yellowriver-custom-menu',
2159
- 'zir': 'application/vnd.zul',
2160
- 'zirz': 'application/vnd.zul',
2161
- 'zaz': 'application/vnd.zzazz.deck+xml',
2162
- 'vxml': 'application/voicexml+xml',
2163
- 'wasm': 'application/wasm',
2164
- 'wif': 'application/watcherinfo+xml',
2165
- 'wgt': 'application/widget',
2166
- 'hlp': 'application/winhlp',
2167
- 'wsdl': 'application/wsdl+xml',
2168
- 'wspolicy': 'application/wspolicy+xml',
2169
- '7z': 'application/x-7z-compressed',
2170
- 'abw': 'application/x-abiword',
2171
- 'ace': 'application/x-ace-compressed',
2172
- 'arj': 'application/x-arj',
2173
- 'aab': 'application/x-authorware-bin',
2174
- 'x32': 'application/x-authorware-bin',
2175
- 'u32': 'application/x-authorware-bin',
2176
- 'vox': 'application/x-authorware-bin',
2177
- 'aam': 'application/x-authorware-map',
2178
- 'aas': 'application/x-authorware-seg',
2179
- 'bcpio': 'application/x-bcpio',
2180
- 'torrent': 'application/x-bittorrent',
2181
- 'blb': 'application/x-blorb',
2182
- 'blorb': 'application/x-blorb',
2183
- 'bz': 'application/x-bzip',
2184
- 'bz2': 'application/x-bzip2',
2185
- 'boz': 'application/x-bzip2',
2186
- 'cbr': 'application/x-cbr',
2187
- 'cba': 'application/x-cbr',
2188
- 'cbt': 'application/x-cbr',
2189
- 'cbz': 'application/x-cbr',
2190
- 'cb7': 'application/x-cbr',
2191
- 'vcd': 'application/x-cdlink',
2192
- 'cfs': 'application/x-cfs-compressed',
2193
- 'chat': 'application/x-chat',
2194
- 'pgn': 'application/x-chess-pgn',
2195
- 'crx': 'application/x-chrome-extension',
2196
- 'cco': 'application/x-cocoa',
2197
- 'nsc': 'application/x-conference',
2198
- 'cpio': 'application/x-cpio',
2199
- 'csh': 'application/x-csh',
2200
- 'udeb': 'application/x-debian-package',
2201
- 'dgc': 'application/x-dgc-compressed',
2202
- 'dir': 'application/x-director',
2203
- 'dcr': 'application/x-director',
2204
- 'dxr': 'application/x-director',
2205
- 'cst': 'application/x-director',
2206
- 'cct': 'application/x-director',
2207
- 'cxt': 'application/x-director',
2208
- 'w3d': 'application/x-director',
2209
- 'fgd': 'application/x-director',
2210
- 'swa': 'application/x-director',
2211
- 'wad': 'application/x-doom',
2212
- 'ncx': 'application/x-dtbncx+xml',
2213
- 'dtb': 'application/x-dtbook+xml',
2214
- 'res': 'application/x-dtbresource+xml',
2215
- 'dvi': 'application/x-dvi',
2216
- 'evy': 'application/x-envoy',
2217
- 'eva': 'application/x-eva',
2218
- 'bdf': 'application/x-font-bdf',
2219
- 'gsf': 'application/x-font-ghostscript',
2220
- 'psf': 'application/x-font-linux-psf',
2221
- 'pcf': 'application/x-font-pcf',
2222
- 'snf': 'application/x-font-snf',
2223
- 'pfa': 'application/x-font-type1',
2224
- 'pfb': 'application/x-font-type1',
2225
- 'pfm': 'application/x-font-type1',
2226
- 'afm': 'application/x-font-type1',
2227
- 'arc': 'application/x-freearc',
2228
- 'spl': 'application/x-futuresplash',
2229
- 'gca': 'application/x-gca-compressed',
2230
- 'ulx': 'application/x-glulx',
2231
- 'gnumeric': 'application/x-gnumeric',
2232
- 'gramps': 'application/x-gramps-xml',
2233
- 'gtar': 'application/x-gtar',
2234
- 'hdf': 'application/x-hdf',
2235
- 'php': 'application/x-httpd-php',
2236
- 'install': 'application/x-install-instructions',
2237
- 'jardiff': 'application/x-java-archive-diff',
2238
- 'jnlp': 'application/x-java-jnlp-file',
2239
- 'kdbx': 'application/x-keepass2',
2240
- 'latex': 'application/x-latex',
2241
- 'luac': 'application/x-lua-bytecode',
2242
- 'lzh': 'application/x-lzh-compressed',
2243
- 'lha': 'application/x-lzh-compressed',
2244
- 'run': 'application/x-makeself',
2245
- 'mie': 'application/x-mie',
2246
- 'prc': 'model/prc',
2247
- 'mobi': 'application/x-mobipocket-ebook',
2248
- 'application': 'application/x-ms-application',
2249
- 'lnk': 'application/x-ms-shortcut',
2250
- 'wmd': 'application/x-ms-wmd',
2251
- 'wmz': 'application/x-msmetafile',
2252
- 'xbap': 'application/x-ms-xbap',
2253
- 'mdb': 'application/x-msaccess',
2254
- 'obd': 'application/x-msbinder',
2255
- 'crd': 'application/x-mscardfile',
2256
- 'clp': 'application/x-msclip',
2257
- 'com': 'application/x-msdownload',
2258
- 'bat': 'application/x-msdownload',
2259
- 'mvb': 'application/x-msmediaview',
2260
- 'm13': 'application/x-msmediaview',
2261
- 'm14': 'application/x-msmediaview',
2262
- 'wmf': 'image/wmf',
2263
- 'emf': 'image/emf',
2264
- 'emz': 'application/x-msmetafile',
2265
- 'mny': 'application/x-msmoney',
2266
- 'pub': 'application/x-mspublisher',
2267
- 'scd': 'application/x-msschedule',
2268
- 'trm': 'application/x-msterminal',
2269
- 'wri': 'application/x-mswrite',
2270
- 'nc': 'application/x-netcdf',
2271
- 'cdf': 'application/x-netcdf',
2272
- 'pac': 'application/x-ns-proxy-autoconfig',
2273
- 'nzb': 'application/x-nzb',
2274
- 'pl': 'application/x-perl',
2275
- 'pm': 'application/x-perl',
2276
- 'p12': 'application/x-pkcs12',
2277
- 'pfx': 'application/x-pkcs12',
2278
- 'p7b': 'application/x-pkcs7-certificates',
2279
- 'spc': 'application/x-pkcs7-certificates',
2280
- 'p7r': 'application/x-pkcs7-certreqresp',
2281
- 'rpm': 'application/x-redhat-package-manager',
2282
- 'ris': 'application/x-research-info-systems',
2283
- 'sea': 'application/x-sea',
2284
- 'sh': 'application/x-sh',
2285
- 'shar': 'application/x-shar',
2286
- 'swf': 'application/x-shockwave-flash',
2287
- 'xap': 'application/x-silverlight-app',
2288
- 'sql': 'application/x-sql',
2289
- 'sit': 'application/x-stuffit',
2290
- 'sitx': 'application/x-stuffitx',
2291
- 'srt': 'application/x-subrip',
2292
- 'sv4cpio': 'application/x-sv4cpio',
2293
- 'sv4crc': 'application/x-sv4crc',
2294
- 't3': 'application/x-t3vm-image',
2295
- 'gam': 'application/x-tads',
2296
- 'tar': 'application/x-tar',
2297
- 'tcl': 'application/x-tcl',
2298
- 'tk': 'application/x-tcl',
2299
- 'tex': 'application/x-tex',
2300
- 'tfm': 'application/x-tex-tfm',
2301
- 'texinfo': 'application/x-texinfo',
2302
- 'texi': 'application/x-texinfo',
2303
- 'obj': 'model/obj',
2304
- 'ustar': 'application/x-ustar',
2305
- 'hdd': 'application/x-virtualbox-hdd',
2306
- 'ova': 'application/x-virtualbox-ova',
2307
- 'ovf': 'application/x-virtualbox-ovf',
2308
- 'vbox': 'application/x-virtualbox-vbox',
2309
- 'vbox-extpack': 'application/x-virtualbox-vbox-extpack',
2310
- 'vdi': 'application/x-virtualbox-vdi',
2311
- 'vhd': 'application/x-virtualbox-vhd',
2312
- 'vmdk': 'application/x-virtualbox-vmdk',
2313
- 'src': 'application/x-wais-source',
2314
- 'webapp': 'application/x-web-app-manifest+json',
2315
- 'der': 'application/x-x509-ca-cert',
2316
- 'crt': 'application/x-x509-ca-cert',
2317
- 'pem': 'application/x-x509-ca-cert',
2318
- 'fig': 'application/x-xfig',
2319
- 'xlf': 'application/xliff+xml',
2320
- 'xpi': 'application/x-xpinstall',
2321
- 'xz': 'application/x-xz',
2322
- 'z1': 'application/x-zmachine',
2323
- 'z2': 'application/x-zmachine',
2324
- 'z3': 'application/x-zmachine',
2325
- 'z4': 'application/x-zmachine',
2326
- 'z5': 'application/x-zmachine',
2327
- 'z6': 'application/x-zmachine',
2328
- 'z7': 'application/x-zmachine',
2329
- 'z8': 'application/x-zmachine',
2330
- 'xaml': 'application/xaml+xml',
2331
- 'xav': 'application/xcap-att+xml',
2332
- 'xca': 'application/xcap-caps+xml',
2333
- 'xdf': 'application/xcap-diff+xml',
2334
- 'xel': 'application/xcap-el+xml',
2335
- 'xns': 'application/xcap-ns+xml',
2336
- 'xenc': 'application/xenc+xml',
2337
- 'xhtml': 'application/xhtml+xml',
2338
- 'xht': 'application/xhtml+xml',
2339
- 'xml': 'text/xml',
2340
- 'xsl': 'application/xslt+xml',
2341
- 'xsd': 'application/xml',
2342
- 'rng': 'application/xml',
2343
- 'dtd': 'application/xml-dtd',
2344
- 'xop': 'application/xop+xml',
2345
- 'xpl': 'application/xproc+xml',
2346
- 'xslt': 'application/xslt+xml',
2347
- 'xspf': 'application/xspf+xml',
2348
- 'mxml': 'application/xv+xml',
2349
- 'xhvml': 'application/xv+xml',
2350
- 'xvml': 'application/xv+xml',
2351
- 'xvm': 'application/xv+xml',
2352
- 'yang': 'application/yang',
2353
- 'yin': 'application/yin+xml',
2354
- 'zip': 'application/zip',
2355
- '3gpp': 'video/3gpp',
2356
- 'adp': 'audio/adpcm',
2357
- 'amr': 'audio/amr',
2358
- 'au': 'audio/basic',
2359
- 'snd': 'audio/basic',
2360
- 'mid': 'audio/midi',
2361
- 'midi': 'audio/midi',
2362
- 'kar': 'audio/midi',
2363
- 'rmi': 'audio/midi',
2364
- 'mxmf': 'audio/mobile-xmf',
2365
- 'mp3': 'audio/mpeg',
2366
- 'm4a': 'audio/x-m4a',
2367
- 'mp4a': 'audio/mp4',
2368
- 'mpga': 'audio/mpeg',
2369
- 'mp2': 'audio/mpeg',
2370
- 'mp2a': 'audio/mpeg',
2371
- 'm2a': 'audio/mpeg',
2372
- 'm3a': 'audio/mpeg',
2373
- 'oga': 'audio/ogg',
2374
- 'ogg': 'audio/ogg',
2375
- 'spx': 'audio/ogg',
2376
- 'opus': 'audio/ogg',
2377
- 's3m': 'audio/s3m',
2378
- 'sil': 'audio/silk',
2379
- 'uva': 'audio/vnd.dece.audio',
2380
- 'uvva': 'audio/vnd.dece.audio',
2381
- 'eol': 'audio/vnd.digital-winds',
2382
- 'dra': 'audio/vnd.dra',
2383
- 'dts': 'audio/vnd.dts',
2384
- 'dtshd': 'audio/vnd.dts.hd',
2385
- 'lvp': 'audio/vnd.lucent.voice',
2386
- 'pya': 'audio/vnd.ms-playready.media.pya',
2387
- 'ecelp4800': 'audio/vnd.nuera.ecelp4800',
2388
- 'ecelp7470': 'audio/vnd.nuera.ecelp7470',
2389
- 'ecelp9600': 'audio/vnd.nuera.ecelp9600',
2390
- 'rip': 'audio/vnd.rip',
2391
- 'wav': 'audio/x-wav',
2392
- 'weba': 'audio/webm',
2393
- 'aac': 'audio/x-aac',
2394
- 'aif': 'audio/x-aiff',
2395
- 'aiff': 'audio/x-aiff',
2396
- 'aifc': 'audio/x-aiff',
2397
- 'caf': 'audio/x-caf',
2398
- 'flac': 'audio/x-flac',
2399
- 'mka': 'audio/x-matroska',
2400
- 'm3u': 'audio/x-mpegurl',
2401
- 'wax': 'audio/x-ms-wax',
2402
- 'wma': 'audio/x-ms-wma',
2403
- 'ram': 'audio/x-pn-realaudio',
2404
- 'ra': 'audio/x-realaudio',
2405
- 'rmp': 'audio/x-pn-realaudio-plugin',
2406
- 'xm': 'audio/xm',
2407
- 'cdx': 'chemical/x-cdx',
2408
- 'cif': 'chemical/x-cif',
2409
- 'cmdf': 'chemical/x-cmdf',
2410
- 'cml': 'chemical/x-cml',
2411
- 'csml': 'chemical/x-csml',
2412
- 'xyz': 'chemical/x-xyz',
2413
- 'ttc': 'font/collection',
2414
- 'otf': 'font/otf',
2415
- 'ttf': 'font/ttf',
2416
- 'woff': 'font/woff',
2417
- 'woff2': 'font/woff2',
2418
- 'exr': 'image/aces',
2419
- 'apng': 'image/apng',
2420
- 'avci': 'image/avci',
2421
- 'avcs': 'image/avcs',
2422
- 'avif': 'image/avif',
2423
- 'bmp': 'image/x-ms-bmp',
2424
- 'cgm': 'image/cgm',
2425
- 'drle': 'image/dicom-rle',
2426
- 'fits': 'image/fits',
2427
- 'g3': 'image/g3fax',
2428
- 'gif': 'image/gif',
2429
- 'heic': 'image/heic',
2430
- 'heics': 'image/heic-sequence',
2431
- 'heif': 'image/heif',
2432
- 'heifs': 'image/heif-sequence',
2433
- 'hej2': 'image/hej2k',
2434
- 'hsj2': 'image/hsj2',
2435
- 'ief': 'image/ief',
2436
- 'jls': 'image/jls',
2437
- 'jp2': 'image/jp2',
2438
- 'jpg2': 'image/jp2',
2439
- 'jpeg': 'image/jpeg',
2440
- 'jpg': 'image/jpeg',
2441
- 'jpe': 'image/jpeg',
2442
- 'jph': 'image/jph',
2443
- 'jhc': 'image/jphc',
2444
- 'jpm': 'video/jpm',
2445
- 'jpx': 'image/jpx',
2446
- 'jpf': 'image/jpx',
2447
- 'jxr': 'image/jxr',
2448
- 'jxra': 'image/jxra',
2449
- 'jxrs': 'image/jxrs',
2450
- 'jxs': 'image/jxs',
2451
- 'jxsc': 'image/jxsc',
2452
- 'jxsi': 'image/jxsi',
2453
- 'jxss': 'image/jxss',
2454
- 'ktx': 'image/ktx',
2455
- 'ktx2': 'image/ktx2',
2456
- 'png': 'image/png',
2457
- 'btif': 'image/prs.btif',
2458
- 'pti': 'image/prs.pti',
2459
- 'sgi': 'image/sgi',
2460
- 'svg': 'image/svg+xml',
2461
- 'svgz': 'image/svg+xml',
2462
- 't38': 'image/t38',
2463
- 'tif': 'image/tiff',
2464
- 'tiff': 'image/tiff',
2465
- 'tfx': 'image/tiff-fx',
2466
- 'psd': 'image/vnd.adobe.photoshop',
2467
- 'azv': 'image/vnd.airzip.accelerator.azv',
2468
- 'uvi': 'image/vnd.dece.graphic',
2469
- 'uvvi': 'image/vnd.dece.graphic',
2470
- 'uvg': 'image/vnd.dece.graphic',
2471
- 'uvvg': 'image/vnd.dece.graphic',
2472
- 'djvu': 'image/vnd.djvu',
2473
- 'djv': 'image/vnd.djvu',
2474
- 'sub': 'text/vnd.dvb.subtitle',
2475
- 'dwg': 'image/vnd.dwg',
2476
- 'dxf': 'image/vnd.dxf',
2477
- 'fbs': 'image/vnd.fastbidsheet',
2478
- 'fpx': 'image/vnd.fpx',
2479
- 'fst': 'image/vnd.fst',
2480
- 'mmr': 'image/vnd.fujixerox.edmics-mmr',
2481
- 'rlc': 'image/vnd.fujixerox.edmics-rlc',
2482
- 'ico': 'image/x-icon',
2483
- 'dds': 'image/vnd.ms-dds',
2484
- 'mdi': 'image/vnd.ms-modi',
2485
- 'wdp': 'image/vnd.ms-photo',
2486
- 'npx': 'image/vnd.net-fpx',
2487
- 'b16': 'image/vnd.pco.b16',
2488
- 'tap': 'image/vnd.tencent.tap',
2489
- 'vtf': 'image/vnd.valve.source.texture',
2490
- 'wbmp': 'image/vnd.wap.wbmp',
2491
- 'xif': 'image/vnd.xiff',
2492
- 'pcx': 'image/x-pcx',
2493
- 'webp': 'image/webp',
2494
- '3ds': 'image/x-3ds',
2495
- 'ras': 'image/x-cmu-raster',
2496
- 'cmx': 'image/x-cmx',
2497
- 'fh': 'image/x-freehand',
2498
- 'fhc': 'image/x-freehand',
2499
- 'fh4': 'image/x-freehand',
2500
- 'fh5': 'image/x-freehand',
2501
- 'fh7': 'image/x-freehand',
2502
- 'jng': 'image/x-jng',
2503
- 'sid': 'image/x-mrsid-image',
2504
- 'pic': 'image/x-pict',
2505
- 'pct': 'image/x-pict',
2506
- 'pnm': 'image/x-portable-anymap',
2507
- 'pbm': 'image/x-portable-bitmap',
2508
- 'pgm': 'image/x-portable-graymap',
2509
- 'ppm': 'image/x-portable-pixmap',
2510
- 'rgb': 'image/x-rgb',
2511
- 'tga': 'image/x-tga',
2512
- 'xbm': 'image/x-xbitmap',
2513
- 'xpm': 'image/x-xpixmap',
2514
- 'xwd': 'image/x-xwindowdump',
2515
- 'disposition-notification': 'message/disposition-notification',
2516
- 'u8msg': 'message/global',
2517
- 'u8dsn': 'message/global-delivery-status',
2518
- 'u8mdn': 'message/global-disposition-notification',
2519
- 'u8hdr': 'message/global-headers',
2520
- 'eml': 'message/rfc822',
2521
- 'mime': 'message/rfc822',
2522
- 'wsc': 'message/vnd.wfa.wsc',
2523
- '3mf': 'model/3mf',
2524
- 'gltf': 'model/gltf+json',
2525
- 'glb': 'model/gltf-binary',
2526
- 'igs': 'model/iges',
2527
- 'iges': 'model/iges',
2528
- 'msh': 'model/mesh',
2529
- 'mesh': 'model/mesh',
2530
- 'silo': 'model/mesh',
2531
- 'mtl': 'model/mtl',
2532
- 'stpx': 'model/step+xml',
2533
- 'stpz': 'model/step+zip',
2534
- 'stpxz': 'model/step-xml+zip',
2535
- 'u3d': 'model/u3d',
2536
- 'dae': 'model/vnd.collada+xml',
2537
- 'dwf': 'model/vnd.dwf',
2538
- 'gdl': 'model/vnd.gdl',
2539
- 'gtw': 'model/vnd.gtw',
2540
- 'mts': 'model/vnd.mts',
2541
- 'ogex': 'model/vnd.opengex',
2542
- 'x_b': 'model/vnd.parasolid.transmit.binary',
2543
- 'x_t': 'model/vnd.parasolid.transmit.text',
2544
- 'vds': 'model/vnd.sap.vds',
2545
- 'usdz': 'model/vnd.usdz+zip',
2546
- 'bsp': 'model/vnd.valve.source.compiled-map',
2547
- 'vtu': 'model/vnd.vtu',
2548
- 'wrl': 'model/vrml',
2549
- 'vrml': 'model/vrml',
2550
- 'x3db': 'model/x3d+fastinfoset',
2551
- 'x3dbz': 'model/x3d+binary',
2552
- 'x3dv': 'model/x3d-vrml',
2553
- 'x3dvz': 'model/x3d+vrml',
2554
- 'x3d': 'model/x3d+xml',
2555
- 'x3dz': 'model/x3d+xml',
2556
- 'appcache': 'text/cache-manifest',
2557
- 'manifest': 'text/cache-manifest',
2558
- 'ics': 'text/calendar',
2559
- 'ifb': 'text/calendar',
2560
- 'coffee': 'text/coffeescript',
2561
- 'litcoffee': 'text/coffeescript',
2562
- 'css': 'text/css',
2563
- 'csv': 'text/csv',
2564
- 'html': 'text/html',
2565
- 'htm': 'text/html',
2566
- 'shtml': 'text/html',
2567
- 'jade': 'text/jade',
2568
- 'jsx': 'text/jsx',
2569
- 'less': 'text/less',
2570
- 'markdown': 'text/markdown',
2571
- 'md': 'text/markdown',
2572
- 'mml': 'text/mathml',
2573
- 'mdx': 'text/mdx',
2574
- 'n3': 'text/n3',
2575
- 'txt': 'text/plain',
2576
- 'text': 'text/plain',
2577
- 'conf': 'text/plain',
2578
- 'def': 'text/plain',
2579
- 'list': 'text/plain',
2580
- 'log': 'text/plain',
2581
- 'in': 'text/plain',
2582
- 'ini': 'text/plain',
2583
- 'dsc': 'text/prs.lines.tag',
2584
- 'rtx': 'text/richtext',
2585
- 'sgml': 'text/sgml',
2586
- 'sgm': 'text/sgml',
2587
- 'shex': 'text/shex',
2588
- 'slim': 'text/slim',
2589
- 'slm': 'text/slim',
2590
- 'spdx': 'text/spdx',
2591
- 'stylus': 'text/stylus',
2592
- 'styl': 'text/stylus',
2593
- 'tsv': 'text/tab-separated-values',
2594
- 't': 'text/troff',
2595
- 'tr': 'text/troff',
2596
- 'roff': 'text/troff',
2597
- 'man': 'text/troff',
2598
- 'me': 'text/troff',
2599
- 'ms': 'text/troff',
2600
- 'ttl': 'text/turtle',
2601
- 'uri': 'text/uri-list',
2602
- 'uris': 'text/uri-list',
2603
- 'urls': 'text/uri-list',
2604
- 'vcard': 'text/vcard',
2605
- 'curl': 'text/vnd.curl',
2606
- 'dcurl': 'text/vnd.curl.dcurl',
2607
- 'mcurl': 'text/vnd.curl.mcurl',
2608
- 'scurl': 'text/vnd.curl.scurl',
2609
- 'ged': 'text/vnd.familysearch.gedcom',
2610
- 'fly': 'text/vnd.fly',
2611
- 'flx': 'text/vnd.fmi.flexstor',
2612
- 'gv': 'text/vnd.graphviz',
2613
- '3dml': 'text/vnd.in3d.3dml',
2614
- 'spot': 'text/vnd.in3d.spot',
2615
- 'jad': 'text/vnd.sun.j2me.app-descriptor',
2616
- 'wml': 'text/vnd.wap.wml',
2617
- 'wmls': 'text/vnd.wap.wmlscript',
2618
- 'vtt': 'text/vtt',
2619
- 's': 'text/x-asm',
2620
- 'asm': 'text/x-asm',
2621
- 'c': 'text/x-c',
2622
- 'cc': 'text/x-c',
2623
- 'cxx': 'text/x-c',
2624
- 'cpp': 'text/x-c',
2625
- 'h': 'text/x-c',
2626
- 'hh': 'text/x-c',
2627
- 'dic': 'text/x-c',
2628
- 'htc': 'text/x-component',
2629
- 'f': 'text/x-fortran',
2630
- 'for': 'text/x-fortran',
2631
- 'f77': 'text/x-fortran',
2632
- 'f90': 'text/x-fortran',
2633
- 'hbs': 'text/x-handlebars-template',
2634
- 'java': 'text/x-java-source',
2635
- 'lua': 'text/x-lua',
2636
- 'mkd': 'text/x-markdown',
2637
- 'nfo': 'text/x-nfo',
2638
- 'opml': 'text/x-opml',
2639
- 'p': 'text/x-pascal',
2640
- 'pas': 'text/x-pascal',
2641
- 'pde': 'text/x-processing',
2642
- 'sass': 'text/x-sass',
2643
- 'scss': 'text/x-scss',
2644
- 'etx': 'text/x-setext',
2645
- 'sfv': 'text/x-sfv',
2646
- 'ymp': 'text/x-suse-ymp',
2647
- 'uu': 'text/x-uuencode',
2648
- 'vcs': 'text/x-vcalendar',
2649
- 'vcf': 'text/x-vcard',
2650
- 'yaml': 'text/yaml',
2651
- 'yml': 'text/yaml',
2652
- '3gp': 'video/3gpp',
2653
- '3g2': 'video/3gpp2',
2654
- 'h261': 'video/h261',
2655
- 'h263': 'video/h263',
2656
- 'h264': 'video/h264',
2657
- 'm4s': 'video/iso.segment',
2658
- 'jpgv': 'video/jpeg',
2659
- 'jpgm': 'video/jpm',
2660
- 'mj2': 'video/mj2',
2661
- 'mjp2': 'video/mj2',
2662
- 'ts': 'video/mp2t',
2663
- 'mp4': 'video/mp4',
2664
- 'mp4v': 'video/mp4',
2665
- 'mpg4': 'video/mp4',
2666
- 'mpeg': 'video/mpeg',
2667
- 'mpg': 'video/mpeg',
2668
- 'mpe': 'video/mpeg',
2669
- 'm1v': 'video/mpeg',
2670
- 'm2v': 'video/mpeg',
2671
- 'ogv': 'video/ogg',
2672
- 'qt': 'video/quicktime',
2673
- 'mov': 'video/quicktime',
2674
- 'uvh': 'video/vnd.dece.hd',
2675
- 'uvvh': 'video/vnd.dece.hd',
2676
- 'uvm': 'video/vnd.dece.mobile',
2677
- 'uvvm': 'video/vnd.dece.mobile',
2678
- 'uvp': 'video/vnd.dece.pd',
2679
- 'uvvp': 'video/vnd.dece.pd',
2680
- 'uvs': 'video/vnd.dece.sd',
2681
- 'uvvs': 'video/vnd.dece.sd',
2682
- 'uvv': 'video/vnd.dece.video',
2683
- 'uvvv': 'video/vnd.dece.video',
2684
- 'dvb': 'video/vnd.dvb.file',
2685
- 'fvt': 'video/vnd.fvt',
2686
- 'mxu': 'video/vnd.mpegurl',
2687
- 'm4u': 'video/vnd.mpegurl',
2688
- 'pyv': 'video/vnd.ms-playready.media.pyv',
2689
- 'uvu': 'video/vnd.uvvu.mp4',
2690
- 'uvvu': 'video/vnd.uvvu.mp4',
2691
- 'viv': 'video/vnd.vivo',
2692
- 'webm': 'video/webm',
2693
- 'f4v': 'video/x-f4v',
2694
- 'fli': 'video/x-fli',
2695
- 'flv': 'video/x-flv',
2696
- 'm4v': 'video/x-m4v',
2697
- 'mkv': 'video/x-matroska',
2698
- 'mk3d': 'video/x-matroska',
2699
- 'mks': 'video/x-matroska',
2700
- 'mng': 'video/x-mng',
2701
- 'asf': 'video/x-ms-asf',
2702
- 'asx': 'video/x-ms-asf',
2703
- 'vob': 'video/x-ms-vob',
2704
- 'wm': 'video/x-ms-wm',
2705
- 'wmv': 'video/x-ms-wmv',
2706
- 'wmx': 'video/x-ms-wmx',
2707
- 'wvx': 'video/x-ms-wvx',
2708
- 'avi': 'video/x-msvideo',
2709
- 'movie': 'video/x-sgi-movie',
2710
- 'smv': 'video/x-smv',
2711
- 'ice': 'x-conference/x-cooltalk',
2712
- };
2713
-
2714
- function getMimeType(path, fallback = null) {
2715
- const ext = (/\.([^.]+)$/.exec(path) || [])[1] || path;
2716
- return extensions[ext] || fallback;
2717
- }
2718
-
2719
- const { stat, readdir } = fs.promises;
2720
- function statFile(path) {
2721
- return stat(path);
2722
- }
2723
- async function serveFile(filePath, options = {}) {
2724
- const { restoreCtx } = useCurrentWooksContext();
2725
- const { status } = useResponse();
2726
- const { setHeader, removeHeader } = useSetHeaders();
2727
- const headers = useHeaders();
2728
- const { method, url } = useRequest();
2729
- const { setCacheControl, setExpires, setPragmaNoCache } = useSetCacheControl();
2730
- const normalizedPath = path__default.normalize(path__default.join(process.cwd(), options.baseDir || '', filePath));
2731
- let fileStats;
2732
- try {
2733
- fileStats = await stat(normalizedPath);
2734
- }
2735
- catch (e) {
2736
- if (options.defaultExt) {
2737
- const ext = path__default.extname(filePath);
2738
- if (!ext) {
2739
- restoreCtx();
2740
- return serveFile(filePath + '.' + options.defaultExt);
2741
- }
2742
- }
2743
- throw new WooksError(404);
2744
- }
2745
- status(200);
2746
- const etag = `"${[fileStats.ino, fileStats.size, fileStats.mtime.toISOString()].join('-')}"`;
2747
- const lastModified = new Date(fileStats.mtime);
2748
- if (isNotModified(etag, lastModified, headers['if-none-match'] || '', headers['if-modified-since'] || '')) {
2749
- status(304);
2750
- return '';
2751
- }
2752
- setHeader('etag', etag);
2753
- setHeader('last-modified', lastModified.toUTCString());
2754
- if (options.cacheControl !== undefined) {
2755
- setCacheControl(options.cacheControl);
2756
- }
2757
- if (options.expires) {
2758
- setExpires(options.expires);
2759
- }
2760
- if (options.pragmaNoCache) {
2761
- setPragmaNoCache(options.pragmaNoCache);
2762
- }
2763
- if (fileStats.isDirectory()) {
2764
- if (options.listDirectory) {
2765
- restoreCtx();
2766
- return listDirectory(normalizedPath);
2767
- }
2768
- else if (options.index) {
2769
- if (filePath[filePath.length - 1] !== '/' && url && url[url.length - 1] !== '/') {
2770
- return new BaseWooksResponse().setStatus(302).setHeader('location', url + '/');
2771
- }
2772
- restoreCtx();
2773
- return serveFile(path__default.join(filePath, options.index), {
2774
- ...options,
2775
- index: '',
2776
- });
2777
- }
2778
- removeHeader('etag');
2779
- removeHeader('last-modified');
2780
- throw new WooksError(404);
2781
- }
2782
- let range = headers.range;
2783
- let start, end;
2784
- let size = fileStats.size;
2785
- if (range) {
2786
- const rangeParts = range.trim().replace(/bytes=/, '').split('-');
2787
- const [s, e] = rangeParts;
2788
- start = parseInt(s);
2789
- end = e ? parseInt(e) : (size - 1);
2790
- end = Math.min(size - 1, end);
2791
- if (start > end || isNaN(start) || isNaN(end)) {
2792
- throw new WooksError(416);
2793
- }
2794
- size = (end - start) + 1;
2795
- const ifRange = headers['if-range'] || '';
2796
- const ifRangeTag = ifRange[0] === '"' ? ifRange : '';
2797
- const ifRangeDate = ifRangeTag ? '' : ifRange;
2798
- if (ifRange && !isNotModified(etag, lastModified, ifRangeTag, ifRangeDate)) {
2799
- status(200);
2800
- size = fileStats.size;
2801
- range = '';
2802
- }
2803
- else {
2804
- setHeader('content-range', `bytes ${start}-${end}/${fileStats.size}`);
2805
- status(206);
2806
- }
2807
- }
2808
- setHeader('accept-ranges', 'bytes');
2809
- setHeader('content-type', getMimeType(normalizedPath) || 'application/octet-stream');
2810
- setHeader('content-length', size);
2811
- if (options.headers) {
2812
- for (const header of Object.keys(options.headers)) {
2813
- setHeader(header, options.headers[header]);
2814
- }
2815
- }
2816
- return method === 'HEAD' ? '' : fs.createReadStream(normalizedPath, !!range ? { start, end } : undefined);
2817
- }
2818
- function isNotModified(etag, lastModified, clientEtag, clientLM) {
2819
- if (clientEtag) {
2820
- const parts = clientEtag.split(',').map(v => v.trim());
2821
- for (const p of parts) {
2822
- if (etag === p) {
2823
- return true;
2824
- }
2825
- }
2826
- return false;
2827
- }
2828
- const date = new Date(clientLM);
2829
- if (date.toString() !== 'Invalid Date' && date.getTime() > lastModified.getTime()) {
2830
- return true;
2831
- }
2832
- return false;
2833
- }
2834
- async function listDirectory(dirPath) {
2835
- const { setContentType } = useSetHeaders();
2836
- const { url } = useRequest();
2837
- const list = await readdir(dirPath);
2838
- const promises = [];
2839
- let detailedList = [];
2840
- for (const item of list) {
2841
- promises.push({ name: item, promise: stat(path__default.join(dirPath, item)) });
2842
- }
2843
- for (const item of promises) {
2844
- const data = await item.promise;
2845
- detailedList.push({
2846
- name: item.name, size: data.size, mtime: data.mtime, dir: data.isDirectory(),
2847
- });
2848
- }
2849
- detailedList = detailedList.sort((a, b) => a.dir === b.dir ? a.name > b.name ? 1 : -1 : a.dir > b.dir ? -1 : 1);
2850
- detailedList.unshift({ name: '..', dir: true });
2851
- setContentType('text/html');
2852
- const styles = '<style type="text/css">\nhtml { font-family: monospace }\n' +
2853
- 'span { padding: 0px 2px }\n' +
2854
- '.text { text-overflow: ellipsis; overflow: hidden; white-space: nowrap; }\n' +
2855
- '.icon { width: 20px; display: inline-block; text-align: center; }\n' +
2856
- '.name { width: 250px; display: inline-block; }\n' +
2857
- '.size { width: 80px; display: inline-block; color: grey; text-align: right; }\n' +
2858
- '.date { width: 200px; display: inline-block; color: grey; text-align: right; }\n' +
2859
- '\n</style>';
2860
- return '<html><head><title>Dir</title> ' + styles + ' </head><body><ul>' +
2861
- detailedList.map(d => `<li> <span class="icon">${d.dir ? '&#128193;' : '&#128462;'}</span>` +
2862
- `<a href="${path__default.join(url || '', d.name)}"><span class="name text">${d.name}</span></a>` +
2863
- `<span class="size text">${d.size && (d.size > 10000 ? (Math.round(d.size / 1024 / 1024).toString() + 'Mb') : (Math.round(d.size / 1024).toString() + 'Kb')) || ''}</span>` +
2864
- `<span class="date text">${d.mtime && d.mtime.toISOString() || ''}</li>`).join('\n') +
2865
- '</ul></body></html>';
2866
- }
2867
-
2868
- exports.BaseWooksResponse = BaseWooksResponse;
2869
- exports.BaseWooksResponseRenderer = BaseWooksResponseRenderer;
2870
156
  exports.Wooks = Wooks;
2871
- exports.WooksError = WooksError;
2872
- exports.WooksErrorRenderer = WooksErrorRenderer;
2873
- exports.clearCacheObject = clearCacheObject;
2874
- exports.contentTypes = contentTypes;
2875
- exports.createResponseFrom = createResponseFrom;
2876
- exports.httpStatusCodes = httpStatusCodes;
2877
- exports.registerBodyCompressor = registerBodyCompressor;
2878
- exports.serveFile = serveFile;
2879
- exports.setTestHttpContext = setTestHttpContext;
2880
- exports.statFile = statFile;
2881
- exports.useAccept = useAccept;
2882
- exports.useAuthorization = useAuthorization;
2883
- exports.useBody = useBody;
2884
- exports.useCacheObject = useCacheObject;
2885
- exports.useCookies = useCookies;
2886
- exports.useCurrentWooksContext = useCurrentWooksContext;
2887
- exports.useHeaders = useHeaders;
2888
- exports.useProxy = useProxy;
2889
- exports.useRequest = useRequest;
2890
- exports.useRespCookie = useRespCookie;
2891
- exports.useRespHeader = useRespHeader;
2892
- exports.useResponse = useResponse;
2893
- exports.useRouteParams = useRouteParams;
2894
- exports.useSearchParams = useSearchParams;
2895
- exports.useSetCacheControl = useSetCacheControl;
2896
- exports.useSetCookies = useSetCookies;
2897
- exports.useSetHeaders = useSetHeaders;
2898
- exports.useStatus = useStatus;