@jsenv/core 39.14.2 → 40.0.0
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.
- package/dist/js/directory_listing.js +16 -9
- package/dist/js/server_events_client.js +2 -2
- package/dist/jsenv_core.js +6974 -10642
- package/package.json +22 -19
- package/src/build/build.js +122 -93
- package/src/build/build_specifier_manager.js +103 -94
- package/src/build/build_urls_generator.js +1 -1
- package/src/build/{version_mappings_injection.js → mappings_injection.js} +62 -21
- package/src/build/start_build_server.js +46 -36
- package/src/dev/start_dev_server.js +246 -248
- package/src/helpers/watch_source_files.js +50 -36
- package/src/kitchen/fetched_content_compliance.js +4 -2
- package/src/kitchen/kitchen.js +31 -24
- package/src/kitchen/url_graph/references.js +10 -2
- package/src/kitchen/url_graph/url_graph.js +3 -0
- package/src/kitchen/url_graph/url_graph_visitor.js +3 -0
- package/src/plugins/autoreload/jsenv_plugin_autoreload_server.js +29 -16
- package/src/plugins/html_syntax_error_fallback/jsenv_plugin_html_syntax_error_fallback.js +1 -1
- package/src/plugins/plugin_controller.js +194 -200
- package/src/plugins/plugins.js +5 -0
- package/src/plugins/protocol_file/client/directory_listing.jsx +5 -0
- package/src/plugins/protocol_file/jsenv_plugin_directory_listing.js +92 -67
- package/src/plugins/protocol_file/jsenv_plugin_fs_redirection.js +17 -7
- package/src/plugins/protocol_file/jsenv_plugin_protocol_file.js +6 -0
- package/src/plugins/protocol_http/jsenv_plugin_protocol_http.js +33 -3
- package/src/plugins/reference_analysis/html/jsenv_plugin_html_reference_analysis.js +15 -22
- package/src/plugins/reference_analysis/js/jsenv_plugin_js_reference_analysis.js +53 -2
- package/src/plugins/resolution_node_esm/jsenv_plugin_node_esm_resolution.js +37 -30
- package/src/plugins/resolution_node_esm/node_esm_resolver.js +4 -8
- package/src/plugins/resolution_web/jsenv_plugin_web_resolution.js +8 -6
- package/src/plugins/server_events/client/server_events_client.js +2 -2
- package/src/plugins/server_events/jsenv_plugin_server_events.js +18 -16
- package/dist/js/ws.js +0 -6863
- package/src/helpers/lookup_package_directory.js +0 -9
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
assertAndNormalizeDirectoryUrl,
|
|
3
3
|
bufferToEtag,
|
|
4
|
+
lookupPackageDirectory,
|
|
4
5
|
} from "@jsenv/filesystem";
|
|
5
6
|
import { createLogger, createTaskLog } from "@jsenv/humanize";
|
|
6
7
|
import {
|
|
@@ -17,11 +18,14 @@ import { urlIsInsideOf, urlToRelativeUrl } from "@jsenv/urls";
|
|
|
17
18
|
import { existsSync, readFileSync } from "node:fs";
|
|
18
19
|
import { defaultRuntimeCompat } from "../build/build.js";
|
|
19
20
|
import { createEventEmitter } from "../helpers/event_emitter.js";
|
|
20
|
-
import { lookupPackageDirectory } from "../helpers/lookup_package_directory.js";
|
|
21
21
|
import { watchSourceFiles } from "../helpers/watch_source_files.js";
|
|
22
22
|
import { WEB_URL_CONVERTER } from "../helpers/web_url_converter.js";
|
|
23
23
|
import { jsenvCoreDirectoryUrl } from "../jsenv_core_directory_url.js";
|
|
24
24
|
import { createKitchen } from "../kitchen/kitchen.js";
|
|
25
|
+
import {
|
|
26
|
+
createPluginController,
|
|
27
|
+
createPluginStore,
|
|
28
|
+
} from "../plugins/plugin_controller.js";
|
|
25
29
|
import { getCorePlugins } from "../plugins/plugins.js";
|
|
26
30
|
import { jsenvPluginServerEvents } from "../plugins/server_events/jsenv_plugin_server_events.js";
|
|
27
31
|
import { parseUserAgentHeader } from "./user_agent.js";
|
|
@@ -56,7 +60,7 @@ export const startDevServer = async ({
|
|
|
56
60
|
keepProcessAlive = true,
|
|
57
61
|
onStop = () => {},
|
|
58
62
|
|
|
59
|
-
sourceFilesConfig,
|
|
63
|
+
sourceFilesConfig = {},
|
|
60
64
|
clientAutoreload = true,
|
|
61
65
|
|
|
62
66
|
// runtimeCompat is the runtimeCompat for the build
|
|
@@ -154,27 +158,26 @@ export const startDevServer = async ({
|
|
|
154
158
|
// x-server-inspect service
|
|
155
159
|
{
|
|
156
160
|
finalServices.push({
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
return { server: "jsenv_dev_server/1" };
|
|
161
|
+
name: "jsenv:server_header",
|
|
162
|
+
routes: [
|
|
163
|
+
{
|
|
164
|
+
endpoint: "GET /.internal/server.json",
|
|
165
|
+
description: "Get information about jsenv dev server",
|
|
166
|
+
availableMediaTypes: ["application/json"],
|
|
167
|
+
declarationSource: import.meta.url,
|
|
168
|
+
fetch: () =>
|
|
169
|
+
Response.json({
|
|
170
|
+
server: "jsenv_dev_server/1",
|
|
171
|
+
sourceDirectoryUrl,
|
|
172
|
+
}),
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
injectResponseProperties: () => {
|
|
176
|
+
return {
|
|
177
|
+
headers: {
|
|
178
|
+
server: "jsenv_dev_server/1",
|
|
179
|
+
},
|
|
180
|
+
};
|
|
178
181
|
},
|
|
179
182
|
});
|
|
180
183
|
}
|
|
@@ -222,6 +225,29 @@ export const startDevServer = async ({
|
|
|
222
225
|
);
|
|
223
226
|
serverStopCallbackSet.add(stopWatchingSourceFiles);
|
|
224
227
|
|
|
228
|
+
const devServerPluginStore = createPluginStore([
|
|
229
|
+
jsenvPluginServerEvents({ clientAutoreload }),
|
|
230
|
+
...plugins,
|
|
231
|
+
...getCorePlugins({
|
|
232
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
233
|
+
mainFilePath: sourceMainFilePath,
|
|
234
|
+
runtimeCompat,
|
|
235
|
+
sourceFilesConfig,
|
|
236
|
+
|
|
237
|
+
referenceAnalysis,
|
|
238
|
+
nodeEsmResolution,
|
|
239
|
+
magicExtensions,
|
|
240
|
+
magicDirectoryIndex,
|
|
241
|
+
directoryListing,
|
|
242
|
+
supervisor,
|
|
243
|
+
injections,
|
|
244
|
+
transpilation,
|
|
245
|
+
|
|
246
|
+
clientAutoreload,
|
|
247
|
+
cacheControl,
|
|
248
|
+
ribbon,
|
|
249
|
+
}),
|
|
250
|
+
]);
|
|
225
251
|
const getOrCreateKitchen = (request) => {
|
|
226
252
|
const { runtimeName, runtimeVersion } = parseUserAgentHeader(
|
|
227
253
|
request.headers["user-agent"] || "",
|
|
@@ -258,27 +284,6 @@ export const startDevServer = async ({
|
|
|
258
284
|
dev: true,
|
|
259
285
|
runtimeCompat,
|
|
260
286
|
clientRuntimeCompat,
|
|
261
|
-
plugins: [
|
|
262
|
-
jsenvPluginServerEvents({ clientAutoreload }),
|
|
263
|
-
...plugins,
|
|
264
|
-
...getCorePlugins({
|
|
265
|
-
rootDirectoryUrl: sourceDirectoryUrl,
|
|
266
|
-
runtimeCompat,
|
|
267
|
-
|
|
268
|
-
referenceAnalysis,
|
|
269
|
-
nodeEsmResolution,
|
|
270
|
-
magicExtensions,
|
|
271
|
-
magicDirectoryIndex,
|
|
272
|
-
directoryListing,
|
|
273
|
-
supervisor,
|
|
274
|
-
injections,
|
|
275
|
-
transpilation,
|
|
276
|
-
|
|
277
|
-
clientAutoreload,
|
|
278
|
-
cacheControl,
|
|
279
|
-
ribbon,
|
|
280
|
-
}),
|
|
281
|
-
],
|
|
282
287
|
supervisor,
|
|
283
288
|
minification: false,
|
|
284
289
|
sourcemaps,
|
|
@@ -365,9 +370,14 @@ export const startDevServer = async ({
|
|
|
365
370
|
);
|
|
366
371
|
},
|
|
367
372
|
);
|
|
373
|
+
const devServerPluginController = createPluginController(
|
|
374
|
+
devServerPluginStore,
|
|
375
|
+
kitchen,
|
|
376
|
+
);
|
|
377
|
+
kitchen.setPluginController(devServerPluginController);
|
|
368
378
|
|
|
369
379
|
serverStopCallbackSet.add(() => {
|
|
370
|
-
|
|
380
|
+
devServerPluginController.callHooks("destroy", kitchen.context);
|
|
371
381
|
});
|
|
372
382
|
kitchenCache.set(runtimeId, kitchen);
|
|
373
383
|
onKitchenCreated(kitchen);
|
|
@@ -375,222 +385,210 @@ export const startDevServer = async ({
|
|
|
375
385
|
};
|
|
376
386
|
|
|
377
387
|
finalServices.push({
|
|
378
|
-
name: "jsenv:
|
|
379
|
-
|
|
388
|
+
name: "jsenv:dev_server_routes",
|
|
389
|
+
augmentRouteFetchSecondArg: (request) => {
|
|
380
390
|
const kitchen = getOrCreateKitchen(request);
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
)
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
specifier: request.resource,
|
|
429
|
-
});
|
|
430
|
-
rootUrlInfo.context.request = null;
|
|
431
|
-
rootUrlInfo.context.requestedUrl = null;
|
|
432
|
-
}
|
|
433
|
-
const urlInfo = reference.urlInfo;
|
|
434
|
-
const ifNoneMatch = request.headers["if-none-match"];
|
|
435
|
-
const urlInfoTargetedByCache = urlInfo.findParentIfInline() || urlInfo;
|
|
436
|
-
|
|
437
|
-
try {
|
|
438
|
-
if (!urlInfo.error && ifNoneMatch) {
|
|
439
|
-
const [clientOriginalContentEtag, clientContentEtag] =
|
|
440
|
-
ifNoneMatch.split("_");
|
|
441
|
-
if (
|
|
442
|
-
urlInfoTargetedByCache.originalContentEtag ===
|
|
443
|
-
clientOriginalContentEtag &&
|
|
444
|
-
urlInfoTargetedByCache.contentEtag === clientContentEtag &&
|
|
445
|
-
urlInfoTargetedByCache.isValid()
|
|
446
|
-
) {
|
|
447
|
-
const headers = {
|
|
448
|
-
"cache-control": `private,max-age=0,must-revalidate`,
|
|
449
|
-
};
|
|
450
|
-
Object.keys(urlInfo.headers).forEach((key) => {
|
|
451
|
-
if (key !== "content-length") {
|
|
452
|
-
headers[key] = urlInfo.headers[key];
|
|
453
|
-
}
|
|
391
|
+
return { kitchen };
|
|
392
|
+
},
|
|
393
|
+
routes: [
|
|
394
|
+
...devServerPluginStore.allDevServerRoutes,
|
|
395
|
+
{
|
|
396
|
+
endpoint: "GET *",
|
|
397
|
+
description: "Serve project files.",
|
|
398
|
+
declarationSource: import.meta.url,
|
|
399
|
+
fetch: async (request, { kitchen }) => {
|
|
400
|
+
const { rootDirectoryUrl, mainFilePath } = kitchen.context;
|
|
401
|
+
let requestResource = request.resource;
|
|
402
|
+
let requestedUrl;
|
|
403
|
+
if (requestResource.startsWith("/@fs/")) {
|
|
404
|
+
const fsRootRelativeUrl = requestResource.slice("/@fs/".length);
|
|
405
|
+
requestedUrl = `file:///${fsRootRelativeUrl}`;
|
|
406
|
+
} else {
|
|
407
|
+
const requestedUrlObject = new URL(
|
|
408
|
+
requestResource === "/"
|
|
409
|
+
? mainFilePath
|
|
410
|
+
: requestResource.slice(1),
|
|
411
|
+
rootDirectoryUrl,
|
|
412
|
+
);
|
|
413
|
+
requestedUrlObject.searchParams.delete("hot");
|
|
414
|
+
requestedUrl = requestedUrlObject.href;
|
|
415
|
+
}
|
|
416
|
+
const { referer } = request.headers;
|
|
417
|
+
const parentUrl = referer
|
|
418
|
+
? WEB_URL_CONVERTER.asFileUrl(referer, {
|
|
419
|
+
origin: request.origin,
|
|
420
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
421
|
+
})
|
|
422
|
+
: sourceDirectoryUrl;
|
|
423
|
+
let reference = kitchen.graph.inferReference(
|
|
424
|
+
request.resource,
|
|
425
|
+
parentUrl,
|
|
426
|
+
);
|
|
427
|
+
if (reference) {
|
|
428
|
+
reference.urlInfo.context.request = request;
|
|
429
|
+
reference.urlInfo.context.requestedUrl = requestedUrl;
|
|
430
|
+
} else {
|
|
431
|
+
const rootUrlInfo = kitchen.graph.rootUrlInfo;
|
|
432
|
+
rootUrlInfo.context.request = request;
|
|
433
|
+
rootUrlInfo.context.requestedUrl = requestedUrl;
|
|
434
|
+
reference = rootUrlInfo.dependencies.createResolveAndFinalize({
|
|
435
|
+
trace: { message: parentUrl },
|
|
436
|
+
type: "http_request",
|
|
437
|
+
specifier: request.resource,
|
|
454
438
|
});
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
headers,
|
|
458
|
-
};
|
|
439
|
+
rootUrlInfo.context.request = null;
|
|
440
|
+
rootUrlInfo.context.requestedUrl = null;
|
|
459
441
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
? {
|
|
477
|
-
"cache-control": "no-store", // for inline file we force no-store when parent is no-store
|
|
478
|
-
}
|
|
479
|
-
: {
|
|
442
|
+
const urlInfo = reference.urlInfo;
|
|
443
|
+
const ifNoneMatch = request.headers["if-none-match"];
|
|
444
|
+
const urlInfoTargetedByCache =
|
|
445
|
+
urlInfo.findParentIfInline() || urlInfo;
|
|
446
|
+
|
|
447
|
+
try {
|
|
448
|
+
if (!urlInfo.error && ifNoneMatch) {
|
|
449
|
+
const [clientOriginalContentEtag, clientContentEtag] =
|
|
450
|
+
ifNoneMatch.split("_");
|
|
451
|
+
if (
|
|
452
|
+
urlInfoTargetedByCache.originalContentEtag ===
|
|
453
|
+
clientOriginalContentEtag &&
|
|
454
|
+
urlInfoTargetedByCache.contentEtag === clientContentEtag &&
|
|
455
|
+
urlInfoTargetedByCache.isValid()
|
|
456
|
+
) {
|
|
457
|
+
const headers = {
|
|
480
458
|
"cache-control": `private,max-age=0,must-revalidate`,
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
(returnValue) => {
|
|
500
|
-
response = composeTwoResponses(response, returnValue);
|
|
501
|
-
},
|
|
502
|
-
);
|
|
503
|
-
return response;
|
|
504
|
-
} catch (error) {
|
|
505
|
-
const originalError = error ? error.cause || error : error;
|
|
506
|
-
if (originalError.asResponse) {
|
|
507
|
-
return originalError.asResponse();
|
|
508
|
-
}
|
|
509
|
-
const code = originalError.code;
|
|
510
|
-
if (code === "PARSE_ERROR") {
|
|
511
|
-
// when possible let browser re-throw the syntax error
|
|
512
|
-
// it's not possible to do that when url info content is not available
|
|
513
|
-
// (happens for js_module_fallback for instance)
|
|
514
|
-
if (urlInfo.content !== undefined) {
|
|
515
|
-
kitchen.context.logger.error(`Error while handling ${request.url}:
|
|
516
|
-
${originalError.reasonCode || originalError.code}
|
|
517
|
-
${error.trace?.message}`);
|
|
518
|
-
return {
|
|
459
|
+
};
|
|
460
|
+
Object.keys(urlInfo.headers).forEach((key) => {
|
|
461
|
+
if (key !== "content-length") {
|
|
462
|
+
headers[key] = urlInfo.headers[key];
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
return {
|
|
466
|
+
status: 304,
|
|
467
|
+
headers,
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
await urlInfo.cook({ request, reference });
|
|
472
|
+
let { response } = urlInfo;
|
|
473
|
+
if (response) {
|
|
474
|
+
return response;
|
|
475
|
+
}
|
|
476
|
+
response = {
|
|
519
477
|
url: reference.url,
|
|
520
478
|
status: 200,
|
|
521
|
-
// reason becomes the http response statusText, it must not contain invalid chars
|
|
522
|
-
// https://github.com/nodejs/node/blob/0c27ca4bc9782d658afeaebcec85ec7b28f1cc35/lib/_http_common.js#L221
|
|
523
|
-
statusText: error.reason,
|
|
524
|
-
statusMessage: originalError.message,
|
|
525
479
|
headers: {
|
|
480
|
+
// when we send eTag to the client the next request to the server
|
|
481
|
+
// will send etag in request headers.
|
|
482
|
+
// If they match jsenv bypass cooking and returns 304
|
|
483
|
+
// This must not happen when a plugin uses "no-store" or "no-cache" as it means
|
|
484
|
+
// plugin logic wants to happens for every request to this url
|
|
485
|
+
...(cacheIsDisabledInResponseHeader(urlInfoTargetedByCache)
|
|
486
|
+
? {
|
|
487
|
+
"cache-control": "no-store", // for inline file we force no-store when parent is no-store
|
|
488
|
+
}
|
|
489
|
+
: {
|
|
490
|
+
"cache-control": `private,max-age=0,must-revalidate`,
|
|
491
|
+
// it's safe to use "_" separator because etag is encoded with base64 (see https://stackoverflow.com/a/13195197)
|
|
492
|
+
"eTag": `${urlInfoTargetedByCache.originalContentEtag}_${urlInfoTargetedByCache.contentEtag}`,
|
|
493
|
+
}),
|
|
494
|
+
...urlInfo.headers,
|
|
526
495
|
"content-type": urlInfo.contentType,
|
|
527
496
|
"content-length": urlInfo.contentLength,
|
|
528
|
-
"cache-control": "no-store",
|
|
529
497
|
},
|
|
530
498
|
body: urlInfo.content,
|
|
499
|
+
timing: urlInfo.timing, // TODO: use something else
|
|
500
|
+
};
|
|
501
|
+
const augmentResponseInfo = {
|
|
502
|
+
...kitchen.context,
|
|
503
|
+
reference,
|
|
504
|
+
urlInfo,
|
|
505
|
+
};
|
|
506
|
+
kitchen.pluginController.callHooks(
|
|
507
|
+
"augmentResponse",
|
|
508
|
+
augmentResponseInfo,
|
|
509
|
+
(returnValue) => {
|
|
510
|
+
response = composeTwoResponses(response, returnValue);
|
|
511
|
+
},
|
|
512
|
+
);
|
|
513
|
+
return response;
|
|
514
|
+
} catch (error) {
|
|
515
|
+
const originalError = error ? error.cause || error : error;
|
|
516
|
+
if (originalError.asResponse) {
|
|
517
|
+
return originalError.asResponse();
|
|
518
|
+
}
|
|
519
|
+
const code = originalError.code;
|
|
520
|
+
if (code === "PARSE_ERROR") {
|
|
521
|
+
// when possible let browser re-throw the syntax error
|
|
522
|
+
// it's not possible to do that when url info content is not available
|
|
523
|
+
// (happens for js_module_fallback for instance)
|
|
524
|
+
if (urlInfo.content !== undefined) {
|
|
525
|
+
kitchen.context.logger
|
|
526
|
+
.error(`Error while handling ${request.url}:
|
|
527
|
+
${originalError.reasonCode || originalError.code}
|
|
528
|
+
${error.trace?.message}`);
|
|
529
|
+
return {
|
|
530
|
+
url: reference.url,
|
|
531
|
+
status: 200,
|
|
532
|
+
// reason becomes the http response statusText, it must not contain invalid chars
|
|
533
|
+
// https://github.com/nodejs/node/blob/0c27ca4bc9782d658afeaebcec85ec7b28f1cc35/lib/_http_common.js#L221
|
|
534
|
+
statusText: error.reason,
|
|
535
|
+
statusMessage: originalError.message,
|
|
536
|
+
headers: {
|
|
537
|
+
"content-type": urlInfo.contentType,
|
|
538
|
+
"content-length": urlInfo.contentLength,
|
|
539
|
+
"cache-control": "no-store",
|
|
540
|
+
},
|
|
541
|
+
body: urlInfo.content,
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
return {
|
|
545
|
+
url: reference.url,
|
|
546
|
+
status: 500,
|
|
547
|
+
statusText: error.reason,
|
|
548
|
+
statusMessage: originalError.message,
|
|
549
|
+
headers: {
|
|
550
|
+
"cache-control": "no-store",
|
|
551
|
+
},
|
|
552
|
+
body: urlInfo.content,
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
if (code === "DIRECTORY_REFERENCE_NOT_ALLOWED") {
|
|
556
|
+
return serveDirectory(reference.url, {
|
|
557
|
+
headers: {
|
|
558
|
+
accept: "text/html",
|
|
559
|
+
},
|
|
560
|
+
canReadDirectory: true,
|
|
561
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
if (code === "NOT_ALLOWED") {
|
|
565
|
+
return {
|
|
566
|
+
url: reference.url,
|
|
567
|
+
status: 403,
|
|
568
|
+
statusText: originalError.reason,
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
if (code === "NOT_FOUND") {
|
|
572
|
+
return {
|
|
573
|
+
url: reference.url,
|
|
574
|
+
status: 404,
|
|
575
|
+
statusText: originalError.reason,
|
|
576
|
+
statusMessage: originalError.message,
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
return {
|
|
580
|
+
url: reference.url,
|
|
581
|
+
status: 500,
|
|
582
|
+
statusText: error.reason,
|
|
583
|
+
statusMessage: error.stack,
|
|
584
|
+
headers: {
|
|
585
|
+
"cache-control": "no-store",
|
|
586
|
+
},
|
|
531
587
|
};
|
|
532
588
|
}
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
statusText: error.reason,
|
|
537
|
-
statusMessage: originalError.message,
|
|
538
|
-
headers: {
|
|
539
|
-
"cache-control": "no-store",
|
|
540
|
-
},
|
|
541
|
-
body: urlInfo.content,
|
|
542
|
-
};
|
|
543
|
-
}
|
|
544
|
-
if (code === "DIRECTORY_REFERENCE_NOT_ALLOWED") {
|
|
545
|
-
return serveDirectory(reference.url, {
|
|
546
|
-
headers: {
|
|
547
|
-
accept: "text/html",
|
|
548
|
-
},
|
|
549
|
-
canReadDirectory: true,
|
|
550
|
-
rootDirectoryUrl: sourceDirectoryUrl,
|
|
551
|
-
});
|
|
552
|
-
}
|
|
553
|
-
if (code === "NOT_ALLOWED") {
|
|
554
|
-
return {
|
|
555
|
-
url: reference.url,
|
|
556
|
-
status: 403,
|
|
557
|
-
statusText: originalError.reason,
|
|
558
|
-
};
|
|
559
|
-
}
|
|
560
|
-
if (code === "NOT_FOUND") {
|
|
561
|
-
return {
|
|
562
|
-
url: reference.url,
|
|
563
|
-
status: 404,
|
|
564
|
-
statusText: originalError.reason,
|
|
565
|
-
statusMessage: originalError.message,
|
|
566
|
-
};
|
|
567
|
-
}
|
|
568
|
-
return {
|
|
569
|
-
url: reference.url,
|
|
570
|
-
status: 500,
|
|
571
|
-
statusText: error.reason,
|
|
572
|
-
statusMessage: error.stack,
|
|
573
|
-
headers: {
|
|
574
|
-
"cache-control": "no-store",
|
|
575
|
-
},
|
|
576
|
-
};
|
|
577
|
-
}
|
|
578
|
-
},
|
|
579
|
-
handleWebsocket: async (websocket, { request }) => {
|
|
580
|
-
// if (true || logLevel === "debug") {
|
|
581
|
-
// console.log("handleWebsocket", websocket, request.headers);
|
|
582
|
-
// }
|
|
583
|
-
const kitchen = getOrCreateKitchen(request);
|
|
584
|
-
const serveWebsocketHookInfo = {
|
|
585
|
-
request,
|
|
586
|
-
websocket,
|
|
587
|
-
context: kitchen.context,
|
|
588
|
-
};
|
|
589
|
-
await kitchen.pluginController.callAsyncHooksUntil(
|
|
590
|
-
"serveWebsocket",
|
|
591
|
-
serveWebsocketHookInfo,
|
|
592
|
-
);
|
|
593
|
-
},
|
|
589
|
+
},
|
|
590
|
+
},
|
|
591
|
+
],
|
|
594
592
|
});
|
|
595
593
|
}
|
|
596
594
|
// jsenv error handler service
|