@lwrjs/core 0.17.2-alpha.1 → 0.17.2-alpha.11
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/build/cjs/index.cjs +2 -4
- package/build/cjs/middleware/asset-middleware.cjs +1 -1
- package/build/cjs/middleware/bundle-middleware.cjs +4 -4
- package/build/cjs/middleware/mapping-middleware.cjs +1 -1
- package/build/cjs/middleware/module-middleware.cjs +4 -4
- package/build/cjs/middleware/request-processor-middleware.cjs +5 -5
- package/build/cjs/middleware/resource-middleware.cjs +2 -2
- package/build/cjs/middleware/utils/error-handling.cjs +36 -9
- package/build/cjs/middleware/utils/identity.cjs +3 -9
- package/build/cjs/middleware/view-middleware.cjs +15 -31
- package/build/es/index.js +3 -5
- package/build/es/middleware/asset-middleware.js +3 -3
- package/build/es/middleware/bundle-middleware.js +4 -5
- package/build/es/middleware/mapping-middleware.js +1 -1
- package/build/es/middleware/module-middleware.js +4 -5
- package/build/es/middleware/request-processor-middleware.js +16 -15
- package/build/es/middleware/resource-middleware.js +2 -2
- package/build/es/middleware/utils/error-handling.d.ts +1 -1
- package/build/es/middleware/utils/error-handling.js +51 -11
- package/build/es/middleware/utils/identity.js +4 -10
- package/build/es/middleware/view-middleware.js +18 -37
- package/package.json +31 -31
package/build/cjs/index.cjs
CHANGED
|
@@ -157,10 +157,8 @@ var LwrApp = class {
|
|
|
157
157
|
try {
|
|
158
158
|
await (0, import_server_warmup.warmupServer)(config, app.getInternalRequestKey());
|
|
159
159
|
} catch (err) {
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
}, import_diagnostics.LwrServerError);
|
|
163
|
-
return reject(diagnostic);
|
|
160
|
+
const e = new import_diagnostics.LwrServerError(import_diagnostics.descriptions.SERVER.WARMUP_ERROR(err.message));
|
|
161
|
+
return reject(e);
|
|
164
162
|
}
|
|
165
163
|
}
|
|
166
164
|
const opts = {serverMode, port};
|
|
@@ -92,7 +92,7 @@ function createAssetMiddleware(context) {
|
|
|
92
92
|
}
|
|
93
93
|
res.status(200).stream(asset.stream());
|
|
94
94
|
} catch (error) {
|
|
95
|
-
if (import_path.default.dirname(assetId.specifier) === (basePath ? basePath : "/") && error instanceof import_diagnostics.
|
|
95
|
+
if (import_path.default.dirname(assetId.specifier) === (basePath ? basePath : "/") && error instanceof import_diagnostics.LwrUnresolvableError && error?.type === "asset") {
|
|
96
96
|
await next();
|
|
97
97
|
return;
|
|
98
98
|
}
|
|
@@ -45,17 +45,17 @@ function createBundleMiddleware(context) {
|
|
|
45
45
|
return async (req, res) => {
|
|
46
46
|
if (!req.validateEnvironmentRequest(appConfig)) {
|
|
47
47
|
res.status(400);
|
|
48
|
-
res.send(import_diagnostics.descriptions.
|
|
48
|
+
res.send(import_diagnostics.descriptions.INVALID.INVALID_ENVIRONMENT(req.params.environment));
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
51
51
|
if (!req.validateJsonRequest()) {
|
|
52
52
|
res.status(400);
|
|
53
|
-
res.send(import_diagnostics.descriptions.
|
|
53
|
+
res.send(import_diagnostics.descriptions.INVALID.INVALID_JSON());
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
56
56
|
if (!req.validateApiVersion(appConfig)) {
|
|
57
57
|
res.status(400);
|
|
58
|
-
res.send(import_diagnostics.descriptions.
|
|
58
|
+
res.send(import_diagnostics.descriptions.INVALID.INVALID_API_VERSION(req.params.apiVersion, appConfig.apiVersion));
|
|
59
59
|
return;
|
|
60
60
|
}
|
|
61
61
|
const {runtimeEnvironment, runtimeParams} = req.getRuntimeContext(defaultRuntimeEnvironment);
|
|
@@ -92,7 +92,7 @@ function createSourceMapMiddleware(context) {
|
|
|
92
92
|
return async (req, res) => {
|
|
93
93
|
if (!req.validateEnvironmentRequest(appConfig)) {
|
|
94
94
|
res.status(400);
|
|
95
|
-
res.send(import_diagnostics.descriptions.
|
|
95
|
+
res.send(import_diagnostics.descriptions.INVALID.INVALID_ENVIRONMENT(req.params.environment));
|
|
96
96
|
return;
|
|
97
97
|
}
|
|
98
98
|
const {runtimeEnvironment} = req.getRuntimeContext(defaultRuntimeEnvironment);
|
|
@@ -41,7 +41,7 @@ function createMappingMiddleware(context) {
|
|
|
41
41
|
return async (req, res) => {
|
|
42
42
|
if (!req.validateEnvironmentRequest(appConfig)) {
|
|
43
43
|
res.status(400);
|
|
44
|
-
res.send(import_diagnostics.descriptions.
|
|
44
|
+
res.send(import_diagnostics.descriptions.INVALID.INVALID_ENVIRONMENT(req.params.environment));
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
47
|
const {runtimeEnvironment, runtimeParams} = req.getRuntimeContext(defaultRuntimeEnvironment);
|
|
@@ -39,17 +39,17 @@ function createModuleMiddleware(context) {
|
|
|
39
39
|
return async (req, res) => {
|
|
40
40
|
if (!req.validateEnvironmentRequest(appConfig)) {
|
|
41
41
|
res.status(400);
|
|
42
|
-
res.send(import_diagnostics.descriptions.
|
|
42
|
+
res.send(import_diagnostics.descriptions.INVALID.INVALID_ENVIRONMENT(req.params.environment));
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
45
|
if (!req.validateJsonRequest()) {
|
|
46
46
|
res.status(400);
|
|
47
|
-
res.send(import_diagnostics.descriptions.
|
|
47
|
+
res.send(import_diagnostics.descriptions.INVALID.INVALID_JSON());
|
|
48
48
|
return;
|
|
49
49
|
}
|
|
50
50
|
if (!req.validateApiVersion(appConfig)) {
|
|
51
51
|
res.status(400);
|
|
52
|
-
res.send(import_diagnostics.descriptions.
|
|
52
|
+
res.send(import_diagnostics.descriptions.INVALID.INVALID_API_VERSION(req.params.apiVersion, appConfig.apiVersion));
|
|
53
53
|
return;
|
|
54
54
|
}
|
|
55
55
|
const {runtimeEnvironment, runtimeParams} = req.getRuntimeContext(defaultRuntimeEnvironment);
|
|
@@ -70,7 +70,7 @@ function createModuleMiddleware(context) {
|
|
|
70
70
|
});
|
|
71
71
|
const {ownHash, linkedSource} = moduleDefinition;
|
|
72
72
|
if (signature !== import_shared_utils.LATEST_SIGNATURE && ownHash !== signature) {
|
|
73
|
-
res.status(404).send(import_diagnostics.descriptions.UNRESOLVABLE.SIGNED_MODULE(moduleId.specifier, signature)
|
|
73
|
+
res.status(404).send(import_diagnostics.descriptions.UNRESOLVABLE.SIGNED_MODULE(moduleId.specifier, signature));
|
|
74
74
|
return;
|
|
75
75
|
}
|
|
76
76
|
if (req.isSiteGeneration()) {
|
|
@@ -28,8 +28,6 @@ __export(exports, {
|
|
|
28
28
|
});
|
|
29
29
|
var import_diagnostics = __toModule(require("@lwrjs/diagnostics"));
|
|
30
30
|
var import_shared_utils = __toModule(require("@lwrjs/shared-utils"));
|
|
31
|
-
var MRT_REQUEST_CLASS = "X-Mobify-Request-Class";
|
|
32
|
-
var MRT_REQUEST_CLASS_KEY = MRT_REQUEST_CLASS.toLowerCase();
|
|
33
31
|
function requestProcessorMiddleware(app, context) {
|
|
34
32
|
const {basePath} = context.runtimeEnvironment;
|
|
35
33
|
app.use(async (req, res, next) => {
|
|
@@ -44,8 +42,10 @@ function requestProcessorMiddleware(app, context) {
|
|
|
44
42
|
});
|
|
45
43
|
}
|
|
46
44
|
}
|
|
47
|
-
requestClass = req.headers[
|
|
45
|
+
requestClass = req.headers[import_shared_utils.MRT_REQUEST_CLASS];
|
|
48
46
|
requestDepth = (0, import_shared_utils.parseRequestDepth)(req.headers, req.query);
|
|
47
|
+
const trueClientIP = req.headers[import_shared_utils.TRUE_CLIENT_IP];
|
|
48
|
+
const correlationID = req.headers[import_shared_utils.CORRELATION_ID];
|
|
49
49
|
const forwarded = req.headers["forwarded"];
|
|
50
50
|
const host = req.headers["host"];
|
|
51
51
|
const forwardedProto = req.headers["x-forwarded-proto"];
|
|
@@ -53,7 +53,7 @@ function requestProcessorMiddleware(app, context) {
|
|
|
53
53
|
if ((0, import_shared_utils.isLambdaEnv)()) {
|
|
54
54
|
import_diagnostics.logger.info({
|
|
55
55
|
label: `request-processor-middleware`,
|
|
56
|
-
message: `Original Url: ${req.originalUrl}, Forwarded: ${forwarded}, X-Forwarded-Proto: ${forwardedProto}, Host: ${host}, Protocol: ${protocol}, ${MRT_REQUEST_CLASS}: ${requestClass}, ${import_shared_utils.REQUEST_DEPTH_HEADER}: ${requestDepth}`
|
|
56
|
+
message: `Original Url: ${req.originalUrl}, Forwarded: ${forwarded}, X-Forwarded-Proto: ${forwardedProto}, Host: ${host}, Protocol: ${protocol}, ${import_shared_utils.MRT_REQUEST_CLASS}: ${requestClass}, ${import_shared_utils.TRUE_CLIENT_IP}: ${trueClientIP}, ${import_shared_utils.CORRELATION_ID}: ${correlationID}, ${import_shared_utils.REQUEST_DEPTH_HEADER}: ${requestDepth}`
|
|
57
57
|
});
|
|
58
58
|
}
|
|
59
59
|
}
|
|
@@ -89,7 +89,7 @@ function requestProcessorMiddleware(app, context) {
|
|
|
89
89
|
} else {
|
|
90
90
|
import_diagnostics.logger.debug({
|
|
91
91
|
label: `request-processor-middleware`,
|
|
92
|
-
message: `${
|
|
92
|
+
message: `${import_shared_utils.MRT_REQUEST_CLASS} ignored ${req.headers ? req.headers[import_shared_utils.MRT_REQUEST_CLASS] : "no-headers"}`
|
|
93
93
|
});
|
|
94
94
|
req.basePath = basePath;
|
|
95
95
|
}
|
|
@@ -33,7 +33,7 @@ function createResourceMiddleware(context) {
|
|
|
33
33
|
const {appConfig, resourceRegistry, runtimeEnvironment: defaultRuntimeEnvironment} = context;
|
|
34
34
|
return async (req, res) => {
|
|
35
35
|
if (!req.validateEnvironmentRequest(appConfig)) {
|
|
36
|
-
res.status(400).send(import_diagnostics.descriptions.
|
|
36
|
+
res.status(400).send(import_diagnostics.descriptions.INVALID.INVALID_ENVIRONMENT(req.params.environment));
|
|
37
37
|
return;
|
|
38
38
|
}
|
|
39
39
|
const {runtimeEnvironment, runtimeParams} = req.getRuntimeContext(defaultRuntimeEnvironment);
|
|
@@ -51,7 +51,7 @@ function createResourceMiddleware(context) {
|
|
|
51
51
|
res.status(200).type(resource.type).stream(resource.stream());
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
|
-
res.status(404).send(import_diagnostics.descriptions.UNRESOLVABLE.RESOURCE(resourceId.specifier, resourceId.version)
|
|
54
|
+
res.status(404).send(import_diagnostics.descriptions.UNRESOLVABLE.RESOURCE(resourceId.specifier, resourceId.version));
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
57
|
function resourceMiddleware(app, context) {
|
|
@@ -28,16 +28,42 @@ __export(exports, {
|
|
|
28
28
|
});
|
|
29
29
|
var import_diagnostics = __toModule(require("@lwrjs/diagnostics"));
|
|
30
30
|
var import_diagnostics2 = __toModule(require("@lwrjs/diagnostics"));
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
var import_shared_utils = __toModule(require("@lwrjs/shared-utils"));
|
|
32
|
+
function addRedirectQueryParam(redirectUrl, depth) {
|
|
33
|
+
const fakeOrigin = "http://parse.com";
|
|
34
|
+
const url = (0, import_shared_utils.isURL)(redirectUrl) ? new URL(redirectUrl) : new URL(`${fakeOrigin}${redirectUrl}`);
|
|
35
|
+
url.searchParams.set(import_shared_utils.REQUEST_DEPTH_HEADER, String(depth + 1));
|
|
36
|
+
return url.toString().replace(fakeOrigin, "");
|
|
37
|
+
}
|
|
38
|
+
function createReturnStatus(error, req, debug) {
|
|
39
|
+
let status = 500, body = error.message || "";
|
|
40
|
+
const headers = {};
|
|
41
|
+
if (error instanceof import_diagnostics.LwrStatusError) {
|
|
42
|
+
status = error.status;
|
|
43
|
+
const rawHeaders = error.headers || {};
|
|
44
|
+
Object.entries(rawHeaders).forEach(([key, value]) => headers[key.toLowerCase()] = value);
|
|
45
|
+
if (status === 301 || status === 302) {
|
|
46
|
+
const location = headers.location;
|
|
47
|
+
if (location && (0, import_shared_utils.isURL)(location) || location?.startsWith("/")) {
|
|
48
|
+
headers.location = addRedirectQueryParam(location, (0, import_shared_utils.parseRequestDepth)(req.headers, req.query));
|
|
49
|
+
} else {
|
|
50
|
+
import_diagnostics2.logger.warn(`[error-middleware] Invalid location header for HTTP status ${status}: "${location}"`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (error instanceof import_diagnostics.LwrInvalidError) {
|
|
55
|
+
status = 400;
|
|
56
|
+
} else if (error instanceof import_diagnostics.LwrUnresolvableError) {
|
|
57
|
+
status = 404;
|
|
58
|
+
} else {
|
|
59
|
+
body = error instanceof import_diagnostics.LwrError ? body : `${import_diagnostics.descriptions.SERVER.SERVER_ERROR(req.originalUrl)}: ${body}`;
|
|
34
60
|
}
|
|
35
|
-
if (
|
|
36
|
-
|
|
61
|
+
if (debug) {
|
|
62
|
+
body = `<div style="font-family:sans-serif;margin:50px;"><h1>${status}: Document generation failed</h1><p>${body.replace(/</g, "<").replace(/>/g, ">")}</p></div>`;
|
|
37
63
|
}
|
|
38
|
-
return {status
|
|
64
|
+
return {status, body, headers: Object.keys(headers).length > 0 ? headers : void 0};
|
|
39
65
|
}
|
|
40
|
-
function handleErrors(middleware) {
|
|
66
|
+
function handleErrors(middleware, isBaseDoc = false) {
|
|
41
67
|
return async (req, res, next) => {
|
|
42
68
|
try {
|
|
43
69
|
await middleware(req, res, next);
|
|
@@ -49,9 +75,10 @@ function handleErrors(middleware) {
|
|
|
49
75
|
} else {
|
|
50
76
|
import_diagnostics2.logger.error(err);
|
|
51
77
|
}
|
|
52
|
-
const {status,
|
|
78
|
+
const {status, body, headers} = createReturnStatus(err, req, req.query.debug !== void 0 && isBaseDoc);
|
|
79
|
+
headers && res.set(headers);
|
|
53
80
|
res.status(status);
|
|
54
|
-
res.send(
|
|
81
|
+
res.send(body);
|
|
55
82
|
}
|
|
56
83
|
};
|
|
57
84
|
}
|
|
@@ -37,9 +37,7 @@ function validateSpecifier(specifer) {
|
|
|
37
37
|
function getModuleIdentity(req, importer) {
|
|
38
38
|
const {specifier, signature} = req.params;
|
|
39
39
|
if (validateSpecifier(specifier) === false) {
|
|
40
|
-
throw
|
|
41
|
-
description: import_diagnostics.descriptions.UNRESOLVABLE.INVALID_SPECIFIER(specifier)
|
|
42
|
-
}, import_diagnostics.LwrUnresolvableError);
|
|
40
|
+
throw new import_diagnostics.LwrInvalidError(import_diagnostics.descriptions.INVALID.INVALID_SPECIFIER(specifier));
|
|
43
41
|
}
|
|
44
42
|
const moduleId = (0, import_shared_utils.explodeSpecifier)(specifier);
|
|
45
43
|
return {
|
|
@@ -63,9 +61,7 @@ function getMappingIdentity(req) {
|
|
|
63
61
|
function getResourceIdentity(req) {
|
|
64
62
|
const {specifier, signature = import_shared_utils.LATEST_SIGNATURE} = req.params;
|
|
65
63
|
if (validateSpecifier(specifier) === false) {
|
|
66
|
-
throw
|
|
67
|
-
description: import_diagnostics.descriptions.UNRESOLVABLE.INVALID_SPECIFIER(specifier)
|
|
68
|
-
}, import_diagnostics.LwrUnresolvableError);
|
|
64
|
+
throw new import_diagnostics.LwrInvalidError(import_diagnostics.descriptions.INVALID.INVALID_SPECIFIER(specifier));
|
|
69
65
|
}
|
|
70
66
|
const resourceId = (0, import_shared_utils.explodeSpecifier)(specifier);
|
|
71
67
|
return {
|
|
@@ -77,9 +73,7 @@ function getAssetIdentity(req) {
|
|
|
77
73
|
const {signature, immutable, assetType: type} = req.params;
|
|
78
74
|
const specifier = type ? process.platform === "win32" ? req.params[0] : "/" + req.params[0] : req.originalUrl.split("?")[0];
|
|
79
75
|
if (validateSpecifier(specifier) === false) {
|
|
80
|
-
throw
|
|
81
|
-
description: import_diagnostics.descriptions.UNRESOLVABLE.INVALID_SPECIFIER(specifier)
|
|
82
|
-
}, import_diagnostics.LwrUnresolvableError);
|
|
76
|
+
throw new import_diagnostics.LwrInvalidError(import_diagnostics.descriptions.INVALID.INVALID_SPECIFIER(specifier));
|
|
83
77
|
}
|
|
84
78
|
return {
|
|
85
79
|
immutable,
|
|
@@ -45,12 +45,12 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
45
45
|
return async (req, res) => {
|
|
46
46
|
if (!req.validateEnvironmentRequest(appConfig)) {
|
|
47
47
|
res.status(400);
|
|
48
|
-
res.send(import_diagnostics.descriptions.
|
|
48
|
+
res.send(import_diagnostics.descriptions.INVALID.INVALID_ENVIRONMENT(req.params.environment));
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
51
51
|
if (!req.validateJsonRequest()) {
|
|
52
52
|
res.status(400);
|
|
53
|
-
res.send(import_diagnostics.descriptions.
|
|
53
|
+
res.send(import_diagnostics.descriptions.INVALID.INVALID_JSON());
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
56
56
|
const {runtimeEnvironment, runtimeParams: defaultRuntimeParams} = req.getRuntimeContext(context.runtimeEnvironment);
|
|
@@ -63,13 +63,15 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
63
63
|
query: req.query,
|
|
64
64
|
requestPath: req.path
|
|
65
65
|
};
|
|
66
|
+
const correlationID = req.headers && req.headers[import_shared_utils.CORRELATION_ID];
|
|
66
67
|
const runtimeParams = {
|
|
67
68
|
...defaultRuntimeParams,
|
|
69
|
+
correlationID,
|
|
68
70
|
url: viewRequest.url,
|
|
69
71
|
params: viewRequest.params,
|
|
70
72
|
query: viewRequest.query,
|
|
71
73
|
cookie: req.headers?.cookie,
|
|
72
|
-
trueClientIP: req.headers && req.headers[
|
|
74
|
+
trueClientIP: req.headers && req.headers[import_shared_utils.TRUE_CLIENT_IP],
|
|
73
75
|
coreProxy: req.getCoreProxy(appConfig.coreProxy ?? void 0, route.bootstrap?.proxyForSSR)
|
|
74
76
|
};
|
|
75
77
|
const resolve = req.isJsonRequest() ? viewHandler.getViewJson : viewHandler.getViewContent;
|
|
@@ -88,6 +90,7 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
88
90
|
}
|
|
89
91
|
}, async (span) => {
|
|
90
92
|
traceId = span.traceId;
|
|
93
|
+
runtimeParams.b3TraceID = traceId;
|
|
91
94
|
const res2 = await resolve.call(viewHandler, viewRequest, route, runtimeEnvironment, runtimeParams);
|
|
92
95
|
span.setAttributes({
|
|
93
96
|
size: byteSize(res2.body)
|
|
@@ -96,7 +99,7 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
96
99
|
});
|
|
97
100
|
resolvedRoute = route;
|
|
98
101
|
} catch (err) {
|
|
99
|
-
if (!errorRoute) {
|
|
102
|
+
if (!errorRoute || runtimeEnvironment.debug) {
|
|
100
103
|
throw err;
|
|
101
104
|
}
|
|
102
105
|
import_diagnostics.logger.error(`[view-middleware] Route Error ${req.originalUrl}`);
|
|
@@ -111,8 +114,11 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
111
114
|
});
|
|
112
115
|
resolvedRoute = errorRoute;
|
|
113
116
|
} finally {
|
|
117
|
+
if (correlationID?.length) {
|
|
118
|
+
res.setHeader(import_shared_utils.CORRELATION_ID, correlationID);
|
|
119
|
+
}
|
|
114
120
|
if (traceId?.length) {
|
|
115
|
-
res.setHeader(
|
|
121
|
+
res.setHeader(import_shared_utils.B3_TRACE_ID, traceId);
|
|
116
122
|
res.set({
|
|
117
123
|
"Server-Timing": (0, import_instrumentation2.getTraceCollector)().getSpansInTrace(traceId)
|
|
118
124
|
});
|
|
@@ -136,24 +142,8 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
136
142
|
}
|
|
137
143
|
}
|
|
138
144
|
let status = resolvedRoute.status || viewResponse.status || 200;
|
|
139
|
-
const viewDefinitionStatus = viewResponse.metadata?.viewDefinition?.status;
|
|
140
145
|
if (viewResponse.status === 301 || viewResponse.status === 302) {
|
|
141
146
|
status = viewResponse.status;
|
|
142
|
-
} else if (viewDefinitionStatus && viewDefinitionStatus.code) {
|
|
143
|
-
const origStatus = status;
|
|
144
|
-
const {code, location} = viewDefinitionStatus;
|
|
145
|
-
const isRedirect = code === 301 || code === 302;
|
|
146
|
-
status = code;
|
|
147
|
-
if (isRedirect) {
|
|
148
|
-
if (location && (0, import_shared_utils.isURL)(location) || location?.startsWith("/")) {
|
|
149
|
-
res.set({
|
|
150
|
-
location: addRedirectQueryParam(location, (0, import_shared_utils.parseRequestDepth)(req.headers, req.query))
|
|
151
|
-
});
|
|
152
|
-
} else {
|
|
153
|
-
status = origStatus;
|
|
154
|
-
import_diagnostics.logger.warn(`[view-middleware] Ignoring invalid location header: "${location}"`);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
147
|
}
|
|
158
148
|
res.status(status);
|
|
159
149
|
const viewResponseBody = viewResponse.body;
|
|
@@ -187,7 +177,7 @@ function createConfigMiddleware(routes, context, viewHandler) {
|
|
|
187
177
|
const {appId, encodedViewPath} = req.params;
|
|
188
178
|
const route = routes.find((route2) => route2.id === appId);
|
|
189
179
|
if (!route) {
|
|
190
|
-
res.status(404).send(import_diagnostics.descriptions.UNRESOLVABLE.APP_CONFIG(appId)
|
|
180
|
+
res.status(404).send(import_diagnostics.descriptions.UNRESOLVABLE.APP_CONFIG(appId));
|
|
191
181
|
return;
|
|
192
182
|
}
|
|
193
183
|
const url = (0, import_shared_utils.decodeViewPath)(encodedViewPath);
|
|
@@ -218,7 +208,7 @@ function createConfigMiddleware(routes, context, viewHandler) {
|
|
|
218
208
|
};
|
|
219
209
|
const viewResponse = await viewHandler.getViewConfiguration(viewRequest, route, runtimeEnvironment, runtimeParams);
|
|
220
210
|
if (!viewResponse) {
|
|
221
|
-
res.status(404).send(import_diagnostics.descriptions.UNRESOLVABLE.VIEW_CONFIG(url)
|
|
211
|
+
res.status(404).send(import_diagnostics.descriptions.UNRESOLVABLE.VIEW_CONFIG(url));
|
|
222
212
|
return;
|
|
223
213
|
}
|
|
224
214
|
if (!res.hasHeader("cache-control")) {
|
|
@@ -238,7 +228,7 @@ function createNotFoundMiddleware(errorRoutes, context, viewHandler) {
|
|
|
238
228
|
return createViewMiddleware(notFoundRoute, errorRoutes, context, viewHandler);
|
|
239
229
|
}
|
|
240
230
|
return (req, res) => {
|
|
241
|
-
res.status(404).send(import_diagnostics.descriptions.UNRESOLVABLE.VIEW(req.originalUrl)
|
|
231
|
+
res.status(404).send(import_diagnostics.descriptions.UNRESOLVABLE.VIEW(req.originalUrl));
|
|
242
232
|
};
|
|
243
233
|
}
|
|
244
234
|
function viewMiddleware(app, context) {
|
|
@@ -264,7 +254,7 @@ function viewMiddleware(app, context) {
|
|
|
264
254
|
}
|
|
265
255
|
}
|
|
266
256
|
import_diagnostics.logger.debug({label: `view-middleware`, message: `Add view paths ${paths}`});
|
|
267
|
-
app.get(paths, (0, import_error_handling.handleErrors)(createViewMiddleware(route, errorRoutes, context, viewHandler)));
|
|
257
|
+
app.get(paths, (0, import_error_handling.handleErrors)(createViewMiddleware(route, errorRoutes, context, viewHandler), true));
|
|
268
258
|
}
|
|
269
259
|
app.get((0, import_shared_utils.getClientBootstrapConfigurationRoutes)(), (0, import_error_handling.handleErrors)(createConfigMiddleware(routes, context, viewHandler)));
|
|
270
260
|
app.get("/" + app.getRegexWildcard(), (0, import_error_handling.handleErrors)(createNotFoundMiddleware(errorRoutes, context, viewHandler)));
|
|
@@ -299,12 +289,6 @@ function addDefaultLocaleRedirects(defaultLocale, defaultLocalePaths, defaultRed
|
|
|
299
289
|
return res.sendStatus(301);
|
|
300
290
|
});
|
|
301
291
|
}
|
|
302
|
-
function addRedirectQueryParam(redirectUrl, depth) {
|
|
303
|
-
const fakeOrigin = "http://parse.com";
|
|
304
|
-
const url = (0, import_shared_utils.isURL)(redirectUrl) ? new URL(redirectUrl) : new URL(`${fakeOrigin}${redirectUrl}`);
|
|
305
|
-
url.searchParams.set(import_shared_utils.REQUEST_DEPTH_KEY, String(depth + 1));
|
|
306
|
-
return url.toString().replace(fakeOrigin, "");
|
|
307
|
-
}
|
|
308
292
|
function byteSize(body) {
|
|
309
293
|
if (Buffer.isBuffer(body)) {
|
|
310
294
|
return body.length;
|
package/build/es/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getFeatureFlags } from '@lwrjs/shared-utils';
|
|
2
2
|
import { createInternalServer } from '@lwrjs/server';
|
|
3
|
-
import { LwrServerError,
|
|
3
|
+
import { LwrServerError, descriptions, logger } from '@lwrjs/diagnostics';
|
|
4
4
|
import { DEFAULT_LWR_BOOTSTRAP_CONFIG, loadConfig, executeConfigHooks, executeStartHooks, executeInstrumentationHooks, executeContextHooks, } from '@lwrjs/config';
|
|
5
5
|
import { loadHooks, loadServices, loadRouteHandlers } from '@lwrjs/config/modules';
|
|
6
6
|
import SiteGenerator from './tools/static-generation.js';
|
|
@@ -152,10 +152,8 @@ export class LwrApp {
|
|
|
152
152
|
await warmupServer(config, app.getInternalRequestKey());
|
|
153
153
|
}
|
|
154
154
|
catch (err) {
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
}, LwrServerError);
|
|
158
|
-
return reject(diagnostic);
|
|
155
|
+
const e = new LwrServerError(descriptions.SERVER.WARMUP_ERROR(err.message));
|
|
156
|
+
return reject(e);
|
|
159
157
|
}
|
|
160
158
|
}
|
|
161
159
|
const opts = { serverMode, port };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getFeatureFlags } from '@lwrjs/shared-utils';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import {
|
|
3
|
+
import { LwrUnresolvableError, logger } from '@lwrjs/diagnostics';
|
|
4
4
|
import { RequestHandlerSpan, getTracer } from '@lwrjs/instrumentation';
|
|
5
5
|
import { getAssetIdentity } from './utils/identity.js';
|
|
6
6
|
import { handleErrors } from './utils/error-handling.js';
|
|
@@ -76,8 +76,8 @@ function createAssetMiddleware(context) {
|
|
|
76
76
|
catch (error) {
|
|
77
77
|
// Ignore asset not found for root asset requests
|
|
78
78
|
if (path.dirname(assetId.specifier) === (basePath ? basePath : '/') &&
|
|
79
|
-
error instanceof
|
|
80
|
-
error?.
|
|
79
|
+
error instanceof LwrUnresolvableError &&
|
|
80
|
+
error?.type === 'asset') {
|
|
81
81
|
// Must await other middleware or this can respond before expected.
|
|
82
82
|
await next();
|
|
83
83
|
return;
|
|
@@ -12,18 +12,17 @@ function createBundleMiddleware(context) {
|
|
|
12
12
|
return async (req, res) => {
|
|
13
13
|
if (!req.validateEnvironmentRequest(appConfig)) {
|
|
14
14
|
res.status(400);
|
|
15
|
-
res.send(descriptions.
|
|
15
|
+
res.send(descriptions.INVALID.INVALID_ENVIRONMENT(req.params.environment));
|
|
16
16
|
return;
|
|
17
17
|
}
|
|
18
18
|
if (!req.validateJsonRequest()) {
|
|
19
19
|
res.status(400);
|
|
20
|
-
res.send(descriptions.
|
|
20
|
+
res.send(descriptions.INVALID.INVALID_JSON());
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
23
|
if (!req.validateApiVersion(appConfig)) {
|
|
24
24
|
res.status(400);
|
|
25
|
-
res.send(descriptions.
|
|
26
|
-
.message);
|
|
25
|
+
res.send(descriptions.INVALID.INVALID_API_VERSION(req.params.apiVersion, appConfig.apiVersion));
|
|
27
26
|
return;
|
|
28
27
|
}
|
|
29
28
|
const { runtimeEnvironment, runtimeParams } = req.getRuntimeContext(defaultRuntimeEnvironment);
|
|
@@ -66,7 +65,7 @@ function createSourceMapMiddleware(context) {
|
|
|
66
65
|
return async (req, res) => {
|
|
67
66
|
if (!req.validateEnvironmentRequest(appConfig)) {
|
|
68
67
|
res.status(400);
|
|
69
|
-
res.send(descriptions.
|
|
68
|
+
res.send(descriptions.INVALID.INVALID_ENVIRONMENT(req.params.environment));
|
|
70
69
|
return;
|
|
71
70
|
}
|
|
72
71
|
const { runtimeEnvironment } = req.getRuntimeContext(defaultRuntimeEnvironment);
|
|
@@ -8,7 +8,7 @@ function createMappingMiddleware(context) {
|
|
|
8
8
|
return async (req, res) => {
|
|
9
9
|
if (!req.validateEnvironmentRequest(appConfig)) {
|
|
10
10
|
res.status(400);
|
|
11
|
-
res.send(descriptions.
|
|
11
|
+
res.send(descriptions.INVALID.INVALID_ENVIRONMENT(req.params.environment));
|
|
12
12
|
return;
|
|
13
13
|
}
|
|
14
14
|
const { runtimeEnvironment, runtimeParams } = req.getRuntimeContext(defaultRuntimeEnvironment);
|
|
@@ -11,18 +11,17 @@ function createModuleMiddleware(context) {
|
|
|
11
11
|
return async (req, res) => {
|
|
12
12
|
if (!req.validateEnvironmentRequest(appConfig)) {
|
|
13
13
|
res.status(400);
|
|
14
|
-
res.send(descriptions.
|
|
14
|
+
res.send(descriptions.INVALID.INVALID_ENVIRONMENT(req.params.environment));
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
17
17
|
if (!req.validateJsonRequest()) {
|
|
18
18
|
res.status(400);
|
|
19
|
-
res.send(descriptions.
|
|
19
|
+
res.send(descriptions.INVALID.INVALID_JSON());
|
|
20
20
|
return;
|
|
21
21
|
}
|
|
22
22
|
if (!req.validateApiVersion(appConfig)) {
|
|
23
23
|
res.status(400);
|
|
24
|
-
res.send(descriptions.
|
|
25
|
-
.message);
|
|
24
|
+
res.send(descriptions.INVALID.INVALID_API_VERSION(req.params.apiVersion, appConfig.apiVersion));
|
|
26
25
|
return;
|
|
27
26
|
}
|
|
28
27
|
const { runtimeEnvironment, runtimeParams } = req.getRuntimeContext(defaultRuntimeEnvironment);
|
|
@@ -48,7 +47,7 @@ function createModuleMiddleware(context) {
|
|
|
48
47
|
const { ownHash, linkedSource } = moduleDefinition;
|
|
49
48
|
// validate the requested instances exists
|
|
50
49
|
if (signature !== LATEST_SIGNATURE && ownHash !== signature) {
|
|
51
|
-
res.status(404).send(descriptions.UNRESOLVABLE.SIGNED_MODULE(moduleId.specifier, signature)
|
|
50
|
+
res.status(404).send(descriptions.UNRESOLVABLE.SIGNED_MODULE(moduleId.specifier, signature));
|
|
52
51
|
return;
|
|
53
52
|
}
|
|
54
53
|
if (req.isSiteGeneration()) {
|
|
@@ -1,15 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Parse passed to us via the X-Mobify-Request-Class.
|
|
3
|
-
*
|
|
4
|
-
* basePath: The dynamic base path
|
|
5
|
-
* '' or undefined -> LWR basePath ''
|
|
6
|
-
* token or /token -> LWR basePath '/token'
|
|
7
|
-
*
|
|
8
|
-
*/
|
|
9
1
|
import { logger } from '@lwrjs/diagnostics';
|
|
10
|
-
import { REQUEST_DEPTH_HEADER, isLambdaEnv, parseRequestDepth } from '@lwrjs/shared-utils';
|
|
11
|
-
const MRT_REQUEST_CLASS = 'X-Mobify-Request-Class';
|
|
12
|
-
const MRT_REQUEST_CLASS_KEY = MRT_REQUEST_CLASS.toLowerCase();
|
|
2
|
+
import { CORRELATION_ID, MRT_REQUEST_CLASS, REQUEST_DEPTH_HEADER, TRUE_CLIENT_IP, isLambdaEnv, parseRequestDepth, } from '@lwrjs/shared-utils';
|
|
13
3
|
export function requestProcessorMiddleware(app, context) {
|
|
14
4
|
const { basePath } = context.runtimeEnvironment;
|
|
15
5
|
app.use(async (req, res, next) => {
|
|
@@ -26,8 +16,10 @@ export function requestProcessorMiddleware(app, context) {
|
|
|
26
16
|
});
|
|
27
17
|
}
|
|
28
18
|
}
|
|
29
|
-
requestClass = req.headers[
|
|
19
|
+
requestClass = req.headers[MRT_REQUEST_CLASS];
|
|
30
20
|
requestDepth = parseRequestDepth(req.headers, req.query);
|
|
21
|
+
const trueClientIP = req.headers[TRUE_CLIENT_IP];
|
|
22
|
+
const correlationID = req.headers[CORRELATION_ID];
|
|
31
23
|
const forwarded = req.headers['forwarded'];
|
|
32
24
|
const host = req.headers['host'];
|
|
33
25
|
const forwardedProto = req.headers['x-forwarded-proto'];
|
|
@@ -36,7 +28,7 @@ export function requestProcessorMiddleware(app, context) {
|
|
|
36
28
|
if (isLambdaEnv()) {
|
|
37
29
|
logger.info({
|
|
38
30
|
label: `request-processor-middleware`,
|
|
39
|
-
message: `Original Url: ${req.originalUrl}, Forwarded: ${forwarded}, X-Forwarded-Proto: ${forwardedProto}, Host: ${host}, Protocol: ${protocol}, ${MRT_REQUEST_CLASS}: ${requestClass}, ${REQUEST_DEPTH_HEADER}: ${requestDepth}`,
|
|
31
|
+
message: `Original Url: ${req.originalUrl}, Forwarded: ${forwarded}, X-Forwarded-Proto: ${forwardedProto}, Host: ${host}, Protocol: ${protocol}, ${MRT_REQUEST_CLASS}: ${requestClass}, ${TRUE_CLIENT_IP}: ${trueClientIP}, ${CORRELATION_ID}: ${correlationID}, ${REQUEST_DEPTH_HEADER}: ${requestDepth}`,
|
|
40
32
|
});
|
|
41
33
|
}
|
|
42
34
|
}
|
|
@@ -81,7 +73,7 @@ export function requestProcessorMiddleware(app, context) {
|
|
|
81
73
|
else {
|
|
82
74
|
logger.debug({
|
|
83
75
|
label: `request-processor-middleware`,
|
|
84
|
-
message: `${
|
|
76
|
+
message: `${MRT_REQUEST_CLASS} ignored ${req.headers ? req.headers[MRT_REQUEST_CLASS] : 'no-headers'}`,
|
|
85
77
|
});
|
|
86
78
|
req.basePath = basePath;
|
|
87
79
|
}
|
|
@@ -89,12 +81,21 @@ export function requestProcessorMiddleware(app, context) {
|
|
|
89
81
|
await next();
|
|
90
82
|
});
|
|
91
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Parse the basePath passed via the X-Mobify-Request-Class header.
|
|
86
|
+
* Example: basePath=/token
|
|
87
|
+
*
|
|
88
|
+
* basePath: The dynamic base path
|
|
89
|
+
* '' or undefined -> LWR basePath ''
|
|
90
|
+
* token or /token -> LWR basePath '/token'
|
|
91
|
+
*
|
|
92
|
+
*/
|
|
92
93
|
function parseRequestClass(requestClass) {
|
|
93
94
|
// If there is no requestClass do not bother parsing
|
|
94
95
|
if (!requestClass) {
|
|
95
96
|
return {};
|
|
96
97
|
}
|
|
97
|
-
// Split the
|
|
98
|
+
// Split the header into individual key-value pairs
|
|
98
99
|
const keyValuePairs = requestClass.split(';');
|
|
99
100
|
// Create an object to store the parsed values
|
|
100
101
|
const parsed = {};
|
|
@@ -5,7 +5,7 @@ function createResourceMiddleware(context) {
|
|
|
5
5
|
const { appConfig, resourceRegistry, runtimeEnvironment: defaultRuntimeEnvironment } = context;
|
|
6
6
|
return async (req, res) => {
|
|
7
7
|
if (!req.validateEnvironmentRequest(appConfig)) {
|
|
8
|
-
res.status(400).send(descriptions.
|
|
8
|
+
res.status(400).send(descriptions.INVALID.INVALID_ENVIRONMENT(req.params.environment));
|
|
9
9
|
return;
|
|
10
10
|
}
|
|
11
11
|
const { runtimeEnvironment, runtimeParams } = req.getRuntimeContext(defaultRuntimeEnvironment);
|
|
@@ -23,7 +23,7 @@ function createResourceMiddleware(context) {
|
|
|
23
23
|
res.status(200).type(resource.type).stream(resource.stream());
|
|
24
24
|
return;
|
|
25
25
|
}
|
|
26
|
-
res.status(404).send(descriptions.UNRESOLVABLE.RESOURCE(resourceId.specifier, resourceId.version)
|
|
26
|
+
res.status(404).send(descriptions.UNRESOLVABLE.RESOURCE(resourceId.specifier, resourceId.version));
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
29
|
export function resourceMiddleware(app, context) {
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { MiddlewareFunction } from '@lwrjs/types';
|
|
2
|
-
export declare function handleErrors(middleware: MiddlewareFunction): MiddlewareFunction;
|
|
2
|
+
export declare function handleErrors(middleware: MiddlewareFunction, isBaseDoc?: boolean): MiddlewareFunction;
|
|
3
3
|
//# sourceMappingURL=error-handling.d.ts.map
|
|
@@ -1,16 +1,53 @@
|
|
|
1
|
-
import { descriptions, DiagnosticsError, LwrUnresolvableError } from '@lwrjs/diagnostics';
|
|
1
|
+
import { descriptions, DiagnosticsError, LwrError, LwrInvalidError, LwrStatusError, LwrUnresolvableError, } from '@lwrjs/diagnostics';
|
|
2
2
|
import { logger } from '@lwrjs/diagnostics';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
import { isURL, parseRequestDepth, REQUEST_DEPTH_HEADER } from '@lwrjs/shared-utils';
|
|
4
|
+
function addRedirectQueryParam(redirectUrl, depth) {
|
|
5
|
+
// add a request depth query param to the URL
|
|
6
|
+
// the depth header cannot be used since headers cannot be added to a redirect
|
|
7
|
+
const fakeOrigin = 'http://parse.com';
|
|
8
|
+
const url = isURL(redirectUrl) ? new URL(redirectUrl) : new URL(`${fakeOrigin}${redirectUrl}`);
|
|
9
|
+
url.searchParams.set(REQUEST_DEPTH_HEADER, String(depth + 1));
|
|
10
|
+
return url.toString().replace(fakeOrigin, '');
|
|
11
|
+
}
|
|
12
|
+
function createReturnStatus(error, req, debug) {
|
|
13
|
+
let status = 500, body = error.message || '';
|
|
14
|
+
const headers = {};
|
|
15
|
+
if (error instanceof LwrStatusError) {
|
|
16
|
+
// handle special HTTP statuses, eg: 301, 302, 429, 503
|
|
17
|
+
status = error.status;
|
|
18
|
+
const rawHeaders = error.headers || {};
|
|
19
|
+
Object.entries(rawHeaders).forEach(([key, value]) => (headers[key.toLowerCase()] = value));
|
|
20
|
+
if (status === 301 || status === 302) {
|
|
21
|
+
// handle redirect
|
|
22
|
+
const location = headers.location;
|
|
23
|
+
if ((location && isURL(location)) || location?.startsWith('/')) {
|
|
24
|
+
headers.location = addRedirectQueryParam(location, parseRequestDepth(req.headers, req.query));
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
logger.warn(`[error-middleware] Invalid location header for HTTP status ${status}: "${location}"`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (error instanceof LwrInvalidError) {
|
|
32
|
+
status = 400;
|
|
33
|
+
}
|
|
34
|
+
else if (error instanceof LwrUnresolvableError) {
|
|
35
|
+
status = 404;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
// catchall: likely a LwrServerError
|
|
39
|
+
body =
|
|
40
|
+
error instanceof LwrError
|
|
41
|
+
? body
|
|
42
|
+
: `${descriptions.SERVER.SERVER_ERROR(req.originalUrl)}: ${body}`;
|
|
7
43
|
}
|
|
8
|
-
if (
|
|
9
|
-
return
|
|
44
|
+
if (debug) {
|
|
45
|
+
// return a debug base doc if debug mode is on
|
|
46
|
+
body = `<div style="font-family:sans-serif;margin:50px;"><h1>${status}: Document generation failed</h1><p>${body.replace(/</g, '<').replace(/>/g, '>')}</p></div>`;
|
|
10
47
|
}
|
|
11
|
-
return { status
|
|
48
|
+
return { status, body, headers: Object.keys(headers).length > 0 ? headers : undefined };
|
|
12
49
|
}
|
|
13
|
-
export function handleErrors(middleware) {
|
|
50
|
+
export function handleErrors(middleware, isBaseDoc = false) {
|
|
14
51
|
return async (req, res, next) => {
|
|
15
52
|
try {
|
|
16
53
|
await middleware(req, res, next);
|
|
@@ -24,9 +61,12 @@ export function handleErrors(middleware) {
|
|
|
24
61
|
else {
|
|
25
62
|
logger.error(err);
|
|
26
63
|
}
|
|
27
|
-
const { status,
|
|
64
|
+
const { status, body, headers } = createReturnStatus(err, req,
|
|
65
|
+
// only return HTML error screen for base doc requests in debug mode
|
|
66
|
+
req.query.debug !== undefined && isBaseDoc);
|
|
67
|
+
headers && res.set(headers);
|
|
28
68
|
res.status(status);
|
|
29
|
-
res.send(
|
|
69
|
+
res.send(body);
|
|
30
70
|
}
|
|
31
71
|
};
|
|
32
72
|
}
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { explodeSpecifier, explodeSpecifiers, LATEST_SIGNATURE } from '@lwrjs/shared-utils';
|
|
2
|
-
import {
|
|
2
|
+
import { descriptions, LwrInvalidError } from '@lwrjs/diagnostics';
|
|
3
3
|
function validateSpecifier(specifer) {
|
|
4
4
|
return specifer.indexOf('../') < 0;
|
|
5
5
|
}
|
|
6
6
|
export function getModuleIdentity(req, importer) {
|
|
7
7
|
const { specifier, signature } = req.params;
|
|
8
8
|
if (validateSpecifier(specifier) === false) {
|
|
9
|
-
throw
|
|
10
|
-
description: descriptions.UNRESOLVABLE.INVALID_SPECIFIER(specifier),
|
|
11
|
-
}, LwrUnresolvableError);
|
|
9
|
+
throw new LwrInvalidError(descriptions.INVALID.INVALID_SPECIFIER(specifier));
|
|
12
10
|
}
|
|
13
11
|
const moduleId = explodeSpecifier(specifier);
|
|
14
12
|
return {
|
|
@@ -32,9 +30,7 @@ export function getMappingIdentity(req) {
|
|
|
32
30
|
export function getResourceIdentity(req) {
|
|
33
31
|
const { specifier, signature = LATEST_SIGNATURE } = req.params;
|
|
34
32
|
if (validateSpecifier(specifier) === false) {
|
|
35
|
-
throw
|
|
36
|
-
description: descriptions.UNRESOLVABLE.INVALID_SPECIFIER(specifier),
|
|
37
|
-
}, LwrUnresolvableError);
|
|
33
|
+
throw new LwrInvalidError(descriptions.INVALID.INVALID_SPECIFIER(specifier));
|
|
38
34
|
}
|
|
39
35
|
const resourceId = explodeSpecifier(specifier);
|
|
40
36
|
return {
|
|
@@ -50,9 +46,7 @@ export function getAssetIdentity(req) {
|
|
|
50
46
|
: '/' + req.params[0]
|
|
51
47
|
: req.originalUrl.split('?')[0];
|
|
52
48
|
if (validateSpecifier(specifier) === false) {
|
|
53
|
-
throw
|
|
54
|
-
description: descriptions.UNRESOLVABLE.INVALID_SPECIFIER(specifier),
|
|
55
|
-
}, LwrUnresolvableError);
|
|
49
|
+
throw new LwrInvalidError(descriptions.INVALID.INVALID_SPECIFIER(specifier));
|
|
56
50
|
}
|
|
57
51
|
return {
|
|
58
52
|
immutable,
|
|
@@ -2,7 +2,7 @@ import { TextEncoder } from 'util';
|
|
|
2
2
|
import { URLSearchParams } from 'url';
|
|
3
3
|
import { descriptions, logger } from '@lwrjs/diagnostics';
|
|
4
4
|
import { getClientRoutes } from '@lwrjs/router';
|
|
5
|
-
import {
|
|
5
|
+
import { B3_TRACE_ID, CORRELATION_ID, TRUE_CLIENT_IP, decodeViewPath, extractRequestParams, getClientBootstrapConfigurationRoutes, isLambdaEnv, isLocalDev, shortestTtl, } from '@lwrjs/shared-utils';
|
|
6
6
|
import { RequestHandlerSpan, getTracer } from '@lwrjs/instrumentation';
|
|
7
7
|
import { handleErrors } from './utils/error-handling.js';
|
|
8
8
|
import { LwrViewHandler } from '@lwrjs/view-registry';
|
|
@@ -17,12 +17,12 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
17
17
|
return async (req, res) => {
|
|
18
18
|
if (!req.validateEnvironmentRequest(appConfig)) {
|
|
19
19
|
res.status(400);
|
|
20
|
-
res.send(descriptions.
|
|
20
|
+
res.send(descriptions.INVALID.INVALID_ENVIRONMENT(req.params.environment));
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
23
|
if (!req.validateJsonRequest()) {
|
|
24
24
|
res.status(400);
|
|
25
|
-
res.send(descriptions.
|
|
25
|
+
res.send(descriptions.INVALID.INVALID_JSON());
|
|
26
26
|
return;
|
|
27
27
|
}
|
|
28
28
|
const { runtimeEnvironment, runtimeParams: defaultRuntimeParams } = req.getRuntimeContext(context.runtimeEnvironment);
|
|
@@ -37,13 +37,15 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
37
37
|
requestPath: req.path,
|
|
38
38
|
};
|
|
39
39
|
// Augment runtime params with viewRequest info
|
|
40
|
+
const correlationID = req.headers && req.headers[CORRELATION_ID];
|
|
40
41
|
const runtimeParams = {
|
|
41
42
|
...defaultRuntimeParams,
|
|
43
|
+
correlationID,
|
|
42
44
|
url: viewRequest.url,
|
|
43
45
|
params: viewRequest.params,
|
|
44
46
|
query: viewRequest.query,
|
|
45
47
|
cookie: req.headers?.cookie,
|
|
46
|
-
trueClientIP: req.headers && req.headers[
|
|
48
|
+
trueClientIP: req.headers && req.headers[TRUE_CLIENT_IP],
|
|
47
49
|
coreProxy: req.getCoreProxy(appConfig.coreProxy ?? undefined, route.bootstrap?.proxyForSSR),
|
|
48
50
|
};
|
|
49
51
|
const resolve = req.isJsonRequest() ? viewHandler.getViewJson : viewHandler.getViewContent;
|
|
@@ -62,6 +64,7 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
62
64
|
},
|
|
63
65
|
}, async (span) => {
|
|
64
66
|
traceId = span.traceId;
|
|
67
|
+
runtimeParams.b3TraceID = traceId;
|
|
65
68
|
const res = await resolve.call(viewHandler, viewRequest, route, runtimeEnvironment, runtimeParams);
|
|
66
69
|
// Add the view size metric
|
|
67
70
|
span.setAttributes({
|
|
@@ -72,7 +75,9 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
72
75
|
resolvedRoute = route;
|
|
73
76
|
}
|
|
74
77
|
catch (err) {
|
|
75
|
-
if (!errorRoute) {
|
|
78
|
+
if (!errorRoute || runtimeEnvironment.debug) {
|
|
79
|
+
// this is handled by the error middleware
|
|
80
|
+
// when debug mode is on, always show the error screen
|
|
76
81
|
throw err;
|
|
77
82
|
}
|
|
78
83
|
// Log Unexpected Routing Errors
|
|
@@ -89,8 +94,11 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
89
94
|
resolvedRoute = errorRoute;
|
|
90
95
|
}
|
|
91
96
|
finally {
|
|
97
|
+
if (correlationID?.length) {
|
|
98
|
+
res.setHeader(CORRELATION_ID, correlationID);
|
|
99
|
+
}
|
|
92
100
|
if (traceId?.length) {
|
|
93
|
-
res.setHeader(
|
|
101
|
+
res.setHeader(B3_TRACE_ID, traceId);
|
|
94
102
|
res.set({
|
|
95
103
|
'Server-Timing': getTraceCollector().getSpansInTrace(traceId),
|
|
96
104
|
});
|
|
@@ -119,29 +127,10 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
119
127
|
}
|
|
120
128
|
}
|
|
121
129
|
let status = resolvedRoute.status || viewResponse.status || 200;
|
|
122
|
-
const viewDefinitionStatus = viewResponse.metadata?.viewDefinition?.status;
|
|
123
130
|
if (viewResponse.status === 301 || viewResponse.status === 302) {
|
|
124
131
|
// route handle redirect status takes precedence
|
|
125
132
|
status = viewResponse.status;
|
|
126
133
|
}
|
|
127
|
-
else if (viewDefinitionStatus && viewDefinitionStatus.code) {
|
|
128
|
-
const origStatus = status;
|
|
129
|
-
const { code, location } = viewDefinitionStatus;
|
|
130
|
-
const isRedirect = code === 301 || code === 302;
|
|
131
|
-
status = code;
|
|
132
|
-
if (isRedirect) {
|
|
133
|
-
if ((location && isURL(location)) || location?.startsWith('/')) {
|
|
134
|
-
res.set({
|
|
135
|
-
location: addRedirectQueryParam(location, parseRequestDepth(req.headers, req.query)),
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
// reset the status in the event of an invalid location when redirecting
|
|
140
|
-
status = origStatus;
|
|
141
|
-
logger.warn(`[view-middleware] Ignoring invalid location header: "${location}"`);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
134
|
res.status(status);
|
|
146
135
|
// LWR@MRT 254 temporary safeguard for "dupe styles" issue causing huge base docs
|
|
147
136
|
// Re-evaluate for removal once we determine it is no longer needed: W-17201070
|
|
@@ -181,7 +170,7 @@ function createConfigMiddleware(routes, context, viewHandler) {
|
|
|
181
170
|
// match the app id to a route
|
|
182
171
|
const route = routes.find((route) => route.id === appId);
|
|
183
172
|
if (!route) {
|
|
184
|
-
res.status(404).send(descriptions.UNRESOLVABLE.APP_CONFIG(appId)
|
|
173
|
+
res.status(404).send(descriptions.UNRESOLVABLE.APP_CONFIG(appId));
|
|
185
174
|
return;
|
|
186
175
|
}
|
|
187
176
|
// decode the resolved view path and extract any params.
|
|
@@ -217,7 +206,7 @@ function createConfigMiddleware(routes, context, viewHandler) {
|
|
|
217
206
|
};
|
|
218
207
|
const viewResponse = await viewHandler.getViewConfiguration(viewRequest, route, runtimeEnvironment, runtimeParams);
|
|
219
208
|
if (!viewResponse) {
|
|
220
|
-
res.status(404).send(descriptions.UNRESOLVABLE.VIEW_CONFIG(url)
|
|
209
|
+
res.status(404).send(descriptions.UNRESOLVABLE.VIEW_CONFIG(url));
|
|
221
210
|
return;
|
|
222
211
|
}
|
|
223
212
|
// Pick the shortest TTL between the view response and route object
|
|
@@ -238,7 +227,7 @@ function createNotFoundMiddleware(errorRoutes, context, viewHandler) {
|
|
|
238
227
|
return createViewMiddleware(notFoundRoute, errorRoutes, context, viewHandler);
|
|
239
228
|
}
|
|
240
229
|
return (req, res) => {
|
|
241
|
-
res.status(404).send(descriptions.UNRESOLVABLE.VIEW(req.originalUrl)
|
|
230
|
+
res.status(404).send(descriptions.UNRESOLVABLE.VIEW(req.originalUrl));
|
|
242
231
|
};
|
|
243
232
|
}
|
|
244
233
|
export function viewMiddleware(app, context) {
|
|
@@ -272,7 +261,7 @@ export function viewMiddleware(app, context) {
|
|
|
272
261
|
}
|
|
273
262
|
}
|
|
274
263
|
logger.debug({ label: `view-middleware`, message: `Add view paths ${paths}` });
|
|
275
|
-
app.get(paths, handleErrors(createViewMiddleware(route, errorRoutes, context, viewHandler)));
|
|
264
|
+
app.get(paths, handleErrors(createViewMiddleware(route, errorRoutes, context, viewHandler), true));
|
|
276
265
|
}
|
|
277
266
|
// create and attach middleware for bootstrap configurations
|
|
278
267
|
app.get(getClientBootstrapConfigurationRoutes(), handleErrors(createConfigMiddleware(routes, context, viewHandler)));
|
|
@@ -325,14 +314,6 @@ function addDefaultLocaleRedirects(defaultLocale, defaultLocalePaths, defaultRed
|
|
|
325
314
|
return res.sendStatus(301);
|
|
326
315
|
});
|
|
327
316
|
}
|
|
328
|
-
function addRedirectQueryParam(redirectUrl, depth) {
|
|
329
|
-
// add a request depth query param to the URL
|
|
330
|
-
// the depth header cannot be used since headers cannot be added to a redirect
|
|
331
|
-
const fakeOrigin = 'http://parse.com';
|
|
332
|
-
const url = isURL(redirectUrl) ? new URL(redirectUrl) : new URL(`${fakeOrigin}${redirectUrl}`);
|
|
333
|
-
url.searchParams.set(REQUEST_DEPTH_KEY, String(depth + 1));
|
|
334
|
-
return url.toString().replace(fakeOrigin, '');
|
|
335
|
-
}
|
|
336
317
|
// Get number of bytes from a string. Different char encodings can effect size per char.
|
|
337
318
|
function byteSize(body) {
|
|
338
319
|
if (Buffer.isBuffer(body)) {
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.17.2-alpha.
|
|
7
|
+
"version": "0.17.2-alpha.11",
|
|
8
8
|
"homepage": "https://developer.salesforce.com/docs/platform/lwr/overview",
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
@@ -43,34 +43,34 @@
|
|
|
43
43
|
"build": "tsc -b"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@lwrjs/app-service": "0.17.2-alpha.
|
|
47
|
-
"@lwrjs/asset-registry": "0.17.2-alpha.
|
|
48
|
-
"@lwrjs/asset-transformer": "0.17.2-alpha.
|
|
49
|
-
"@lwrjs/base-view-provider": "0.17.2-alpha.
|
|
50
|
-
"@lwrjs/base-view-transformer": "0.17.2-alpha.
|
|
51
|
-
"@lwrjs/client-modules": "0.17.2-alpha.
|
|
52
|
-
"@lwrjs/config": "0.17.2-alpha.
|
|
53
|
-
"@lwrjs/diagnostics": "0.17.2-alpha.
|
|
54
|
-
"@lwrjs/esbuild": "0.17.2-alpha.
|
|
55
|
-
"@lwrjs/fs-asset-provider": "0.17.2-alpha.
|
|
56
|
-
"@lwrjs/fs-watch": "0.17.2-alpha.
|
|
57
|
-
"@lwrjs/html-view-provider": "0.17.2-alpha.
|
|
58
|
-
"@lwrjs/instrumentation": "0.17.2-alpha.
|
|
59
|
-
"@lwrjs/loader": "0.17.2-alpha.
|
|
60
|
-
"@lwrjs/lwc-module-provider": "0.17.2-alpha.
|
|
61
|
-
"@lwrjs/lwc-ssr": "0.17.2-alpha.
|
|
62
|
-
"@lwrjs/markdown-view-provider": "0.17.2-alpha.
|
|
63
|
-
"@lwrjs/module-bundler": "0.17.2-alpha.
|
|
64
|
-
"@lwrjs/module-registry": "0.17.2-alpha.
|
|
65
|
-
"@lwrjs/npm-module-provider": "0.17.2-alpha.
|
|
66
|
-
"@lwrjs/nunjucks-view-provider": "0.17.2-alpha.
|
|
67
|
-
"@lwrjs/o11y": "0.17.2-alpha.
|
|
68
|
-
"@lwrjs/resource-registry": "0.17.2-alpha.
|
|
69
|
-
"@lwrjs/router": "0.17.2-alpha.
|
|
70
|
-
"@lwrjs/server": "0.17.2-alpha.
|
|
71
|
-
"@lwrjs/shared-utils": "0.17.2-alpha.
|
|
72
|
-
"@lwrjs/static": "0.17.2-alpha.
|
|
73
|
-
"@lwrjs/view-registry": "0.17.2-alpha.
|
|
46
|
+
"@lwrjs/app-service": "0.17.2-alpha.11",
|
|
47
|
+
"@lwrjs/asset-registry": "0.17.2-alpha.11",
|
|
48
|
+
"@lwrjs/asset-transformer": "0.17.2-alpha.11",
|
|
49
|
+
"@lwrjs/base-view-provider": "0.17.2-alpha.11",
|
|
50
|
+
"@lwrjs/base-view-transformer": "0.17.2-alpha.11",
|
|
51
|
+
"@lwrjs/client-modules": "0.17.2-alpha.11",
|
|
52
|
+
"@lwrjs/config": "0.17.2-alpha.11",
|
|
53
|
+
"@lwrjs/diagnostics": "0.17.2-alpha.11",
|
|
54
|
+
"@lwrjs/esbuild": "0.17.2-alpha.11",
|
|
55
|
+
"@lwrjs/fs-asset-provider": "0.17.2-alpha.11",
|
|
56
|
+
"@lwrjs/fs-watch": "0.17.2-alpha.11",
|
|
57
|
+
"@lwrjs/html-view-provider": "0.17.2-alpha.11",
|
|
58
|
+
"@lwrjs/instrumentation": "0.17.2-alpha.11",
|
|
59
|
+
"@lwrjs/loader": "0.17.2-alpha.11",
|
|
60
|
+
"@lwrjs/lwc-module-provider": "0.17.2-alpha.11",
|
|
61
|
+
"@lwrjs/lwc-ssr": "0.17.2-alpha.11",
|
|
62
|
+
"@lwrjs/markdown-view-provider": "0.17.2-alpha.11",
|
|
63
|
+
"@lwrjs/module-bundler": "0.17.2-alpha.11",
|
|
64
|
+
"@lwrjs/module-registry": "0.17.2-alpha.11",
|
|
65
|
+
"@lwrjs/npm-module-provider": "0.17.2-alpha.11",
|
|
66
|
+
"@lwrjs/nunjucks-view-provider": "0.17.2-alpha.11",
|
|
67
|
+
"@lwrjs/o11y": "0.17.2-alpha.11",
|
|
68
|
+
"@lwrjs/resource-registry": "0.17.2-alpha.11",
|
|
69
|
+
"@lwrjs/router": "0.17.2-alpha.11",
|
|
70
|
+
"@lwrjs/server": "0.17.2-alpha.11",
|
|
71
|
+
"@lwrjs/shared-utils": "0.17.2-alpha.11",
|
|
72
|
+
"@lwrjs/static": "0.17.2-alpha.11",
|
|
73
|
+
"@lwrjs/view-registry": "0.17.2-alpha.11",
|
|
74
74
|
"chokidar": "^3.6.0",
|
|
75
75
|
"esbuild": "^0.9.7",
|
|
76
76
|
"fs-extra": "^11.2.0",
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"ws": "^8.18.0"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
|
-
"@lwrjs/types": "0.17.2-alpha.
|
|
83
|
+
"@lwrjs/types": "0.17.2-alpha.11",
|
|
84
84
|
"@types/ws": "^8.5.12",
|
|
85
85
|
"memfs": "^4.13.0"
|
|
86
86
|
},
|
|
@@ -93,5 +93,5 @@
|
|
|
93
93
|
"volta": {
|
|
94
94
|
"extends": "../../../package.json"
|
|
95
95
|
},
|
|
96
|
-
"gitHead": "
|
|
96
|
+
"gitHead": "72217912e6c17e617413044743892582be5599a0"
|
|
97
97
|
}
|