@lwrjs/core 0.17.2-alpha.3 → 0.17.2-alpha.31
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/middleware/bundle-middleware.cjs +4 -4
- package/build/cjs/middleware/mapping-middleware.cjs +1 -1
- package/build/cjs/middleware/module-middleware.cjs +3 -3
- package/build/cjs/middleware/request-processor-middleware.cjs +10 -5
- package/build/cjs/middleware/resource-middleware.cjs +1 -1
- package/build/cjs/middleware/utils/error-handling.cjs +37 -10
- package/build/cjs/middleware/utils/identity.cjs +3 -3
- package/build/cjs/middleware/view-middleware.cjs +24 -35
- package/build/es/index.js +12 -1
- package/build/es/middleware/bundle-middleware.js +4 -4
- package/build/es/middleware/hmr-middleware.js +5 -0
- package/build/es/middleware/mapping-middleware.js +1 -1
- package/build/es/middleware/module-middleware.js +3 -3
- package/build/es/middleware/request-processor-middleware.js +21 -15
- package/build/es/middleware/resource-middleware.js +1 -1
- package/build/es/middleware/utils/error-handling.d.ts +1 -1
- package/build/es/middleware/utils/error-handling.js +54 -12
- package/build/es/middleware/utils/identity.js +4 -4
- package/build/es/middleware/view-middleware.js +28 -39
- package/build/es/tools/static-generation.js +2 -0
- package/build/es/tools/utils/network-dispatcher.js +3 -0
- package/package.json +32 -32
|
@@ -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);
|
|
@@ -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,16 +42,23 @@ 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"];
|
|
52
52
|
const protocol = req.protocol;
|
|
53
|
+
const cookieLength = req.headers["cookie"]?.length || 0;
|
|
54
|
+
let cookieMsg = `Cookie length: ${cookieLength}`;
|
|
55
|
+
if (cookieLength) {
|
|
56
|
+
cookieMsg += `, Cookie has '__Secure-has-sid': ${!!req.cookie("__Secure-has-sid")}, Cookie has 'sid': ${!!req.cookie("sid")}`;
|
|
57
|
+
}
|
|
53
58
|
if ((0, import_shared_utils.isLambdaEnv)()) {
|
|
54
59
|
import_diagnostics.logger.info({
|
|
55
60
|
label: `request-processor-middleware`,
|
|
56
|
-
message: `Original Url: ${req.originalUrl}, Forwarded: ${forwarded}, X-Forwarded-Proto: ${forwardedProto}, Host: ${host},
|
|
61
|
+
message: `Original Url: ${req.originalUrl}, Forwarded: ${forwarded}, X-Forwarded-Proto: ${forwardedProto}, Host: ${host}, Protocol: ${protocol}, ${cookieMsg}, ${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
62
|
});
|
|
58
63
|
}
|
|
59
64
|
}
|
|
@@ -89,7 +94,7 @@ function requestProcessorMiddleware(app, context) {
|
|
|
89
94
|
} else {
|
|
90
95
|
import_diagnostics.logger.debug({
|
|
91
96
|
label: `request-processor-middleware`,
|
|
92
|
-
message: `${
|
|
97
|
+
message: `${import_shared_utils.MRT_REQUEST_CLASS} ignored ${req.headers ? req.headers[import_shared_utils.MRT_REQUEST_CLASS] : "no-headers"}`
|
|
93
98
|
});
|
|
94
99
|
req.basePath = basePath;
|
|
95
100
|
}
|
|
@@ -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);
|
|
@@ -28,16 +28,43 @@ __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, isBaseDoc) {
|
|
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 = isBaseDoc ? 500 : 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>`;
|
|
63
|
+
status = 200;
|
|
37
64
|
}
|
|
38
|
-
return {status
|
|
65
|
+
return {status, body, headers: Object.keys(headers).length > 0 ? headers : void 0};
|
|
39
66
|
}
|
|
40
|
-
function handleErrors(middleware) {
|
|
67
|
+
function handleErrors(middleware, isBaseDoc = false) {
|
|
41
68
|
return async (req, res, next) => {
|
|
42
69
|
try {
|
|
43
70
|
await middleware(req, res, next);
|
|
@@ -49,9 +76,9 @@ function handleErrors(middleware) {
|
|
|
49
76
|
} else {
|
|
50
77
|
import_diagnostics2.logger.error(err);
|
|
51
78
|
}
|
|
52
|
-
const {status,
|
|
53
|
-
res.
|
|
54
|
-
res.send(
|
|
79
|
+
const {status, body, headers} = createReturnStatus(err, req, req.query.debug !== void 0 && isBaseDoc, isBaseDoc);
|
|
80
|
+
headers && res.set(headers);
|
|
81
|
+
res.status(status).send(body);
|
|
55
82
|
}
|
|
56
83
|
};
|
|
57
84
|
}
|
|
@@ -37,7 +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 new import_diagnostics.
|
|
40
|
+
throw new import_diagnostics.LwrInvalidError(import_diagnostics.descriptions.INVALID.INVALID_SPECIFIER(specifier));
|
|
41
41
|
}
|
|
42
42
|
const moduleId = (0, import_shared_utils.explodeSpecifier)(specifier);
|
|
43
43
|
return {
|
|
@@ -61,7 +61,7 @@ function getMappingIdentity(req) {
|
|
|
61
61
|
function getResourceIdentity(req) {
|
|
62
62
|
const {specifier, signature = import_shared_utils.LATEST_SIGNATURE} = req.params;
|
|
63
63
|
if (validateSpecifier(specifier) === false) {
|
|
64
|
-
throw new import_diagnostics.
|
|
64
|
+
throw new import_diagnostics.LwrInvalidError(import_diagnostics.descriptions.INVALID.INVALID_SPECIFIER(specifier));
|
|
65
65
|
}
|
|
66
66
|
const resourceId = (0, import_shared_utils.explodeSpecifier)(specifier);
|
|
67
67
|
return {
|
|
@@ -73,7 +73,7 @@ function getAssetIdentity(req) {
|
|
|
73
73
|
const {signature, immutable, assetType: type} = req.params;
|
|
74
74
|
const specifier = type ? process.platform === "win32" ? req.params[0] : "/" + req.params[0] : req.originalUrl.split("?")[0];
|
|
75
75
|
if (validateSpecifier(specifier) === false) {
|
|
76
|
-
throw new import_diagnostics.
|
|
76
|
+
throw new import_diagnostics.LwrInvalidError(import_diagnostics.descriptions.INVALID.INVALID_SPECIFIER(specifier));
|
|
77
77
|
}
|
|
78
78
|
return {
|
|
79
79
|
immutable,
|
|
@@ -26,17 +26,16 @@ __markAsModule(exports);
|
|
|
26
26
|
__export(exports, {
|
|
27
27
|
viewMiddleware: () => viewMiddleware
|
|
28
28
|
});
|
|
29
|
-
var import_util = __toModule(require("util"));
|
|
30
29
|
var import_url = __toModule(require("url"));
|
|
30
|
+
var import_util = __toModule(require("util"));
|
|
31
|
+
var import_zlib = __toModule(require("zlib"));
|
|
31
32
|
var import_diagnostics = __toModule(require("@lwrjs/diagnostics"));
|
|
33
|
+
var import_instrumentation = __toModule(require("@lwrjs/instrumentation"));
|
|
32
34
|
var import_router = __toModule(require("@lwrjs/router"));
|
|
33
35
|
var import_shared_utils = __toModule(require("@lwrjs/shared-utils"));
|
|
34
|
-
var import_instrumentation = __toModule(require("@lwrjs/instrumentation"));
|
|
35
|
-
var import_error_handling = __toModule(require("./utils/error-handling.cjs"));
|
|
36
36
|
var import_view_registry = __toModule(require("@lwrjs/view-registry"));
|
|
37
|
-
var import_instrumentation2 = __toModule(require("@lwrjs/instrumentation"));
|
|
38
|
-
var import_zlib = __toModule(require("zlib"));
|
|
39
37
|
var import_compression = __toModule(require("./utils/compression.cjs"));
|
|
38
|
+
var import_error_handling = __toModule(require("./utils/error-handling.cjs"));
|
|
40
39
|
function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
41
40
|
const errorRoute = errorRoutes.find((route2) => route2.status === 500);
|
|
42
41
|
const appConfig = context.appConfig;
|
|
@@ -45,12 +44,12 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
45
44
|
return async (req, res) => {
|
|
46
45
|
if (!req.validateEnvironmentRequest(appConfig)) {
|
|
47
46
|
res.status(400);
|
|
48
|
-
res.send(import_diagnostics.descriptions.
|
|
47
|
+
res.send(import_diagnostics.descriptions.INVALID.INVALID_ENVIRONMENT(req.params.environment));
|
|
49
48
|
return;
|
|
50
49
|
}
|
|
51
50
|
if (!req.validateJsonRequest()) {
|
|
52
51
|
res.status(400);
|
|
53
|
-
res.send(import_diagnostics.descriptions.
|
|
52
|
+
res.send(import_diagnostics.descriptions.INVALID.INVALID_JSON());
|
|
54
53
|
return;
|
|
55
54
|
}
|
|
56
55
|
const {runtimeEnvironment, runtimeParams: defaultRuntimeParams} = req.getRuntimeContext(context.runtimeEnvironment);
|
|
@@ -69,13 +68,15 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
69
68
|
params: viewRequest.params,
|
|
70
69
|
query: viewRequest.query,
|
|
71
70
|
cookie: req.headers?.cookie,
|
|
72
|
-
trueClientIP: req.headers
|
|
71
|
+
trueClientIP: req.headers?.[import_shared_utils.TRUE_CLIENT_IP],
|
|
72
|
+
correlationID: req.headers?.[import_shared_utils.CORRELATION_ID],
|
|
73
73
|
coreProxy: req.getCoreProxy(appConfig.coreProxy ?? void 0, route.bootstrap?.proxyForSSR)
|
|
74
74
|
};
|
|
75
75
|
const resolve = req.isJsonRequest() ? viewHandler.getViewJson : viewHandler.getViewContent;
|
|
76
76
|
let viewResponse;
|
|
77
77
|
let resolvedRoute;
|
|
78
78
|
let traceId;
|
|
79
|
+
let headers = {};
|
|
79
80
|
try {
|
|
80
81
|
viewResponse = await (0, import_instrumentation.getTracer)().trace({
|
|
81
82
|
name: import_instrumentation.RequestHandlerSpan.GetView,
|
|
@@ -87,7 +88,9 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
87
88
|
locale: runtimeParams.locale
|
|
88
89
|
}
|
|
89
90
|
}, async (span) => {
|
|
91
|
+
runtimeParams.viewSpanID = span.spanId;
|
|
90
92
|
traceId = span.traceId;
|
|
93
|
+
headers = (0, import_shared_utils.getTraceHeaders)(runtimeParams, span);
|
|
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,18 +114,26 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
111
114
|
});
|
|
112
115
|
resolvedRoute = errorRoute;
|
|
113
116
|
} finally {
|
|
117
|
+
if (Object.keys(headers).length)
|
|
118
|
+
res.set(headers);
|
|
114
119
|
if (traceId?.length) {
|
|
115
|
-
res.setHeader("x-trace-id", traceId);
|
|
116
120
|
res.set({
|
|
117
|
-
"Server-Timing": (0,
|
|
121
|
+
"Server-Timing": (0, import_instrumentation.getTraceCollector)().getSpansInTrace(traceId)
|
|
118
122
|
});
|
|
119
|
-
(0,
|
|
123
|
+
(0, import_instrumentation.getTraceCollector)().dropTrace(traceId);
|
|
120
124
|
}
|
|
121
125
|
}
|
|
122
126
|
if (req.isSiteGeneration()) {
|
|
123
127
|
res.setSiteGenerationMetadata(viewResponse.metadata);
|
|
124
128
|
}
|
|
125
129
|
res.type("text/html");
|
|
130
|
+
if ((0, import_shared_utils.isLocalDev)() || (0, import_shared_utils.isLocalPreview)()) {
|
|
131
|
+
if ((0, import_shared_utils.isLocalAuthEnabled)()) {
|
|
132
|
+
res.setHeader("Set-Cookie", "LocalAuthenticationEnabled=1;");
|
|
133
|
+
} else {
|
|
134
|
+
res.setHeader("Set-Cookie", "LocalAuthenticationEnabled=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT;");
|
|
135
|
+
}
|
|
136
|
+
}
|
|
126
137
|
if (viewResponse.headers) {
|
|
127
138
|
if ((0, import_shared_utils.isLocalDev)()) {
|
|
128
139
|
delete viewResponse.headers["content-security-policy"];
|
|
@@ -136,24 +147,8 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
136
147
|
}
|
|
137
148
|
}
|
|
138
149
|
let status = resolvedRoute.status || viewResponse.status || 200;
|
|
139
|
-
const viewDefinitionStatus = viewResponse.metadata?.viewDefinition?.status;
|
|
140
150
|
if (viewResponse.status === 301 || viewResponse.status === 302) {
|
|
141
151
|
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
152
|
}
|
|
158
153
|
res.status(status);
|
|
159
154
|
const viewResponseBody = viewResponse.body;
|
|
@@ -264,7 +259,7 @@ function viewMiddleware(app, context) {
|
|
|
264
259
|
}
|
|
265
260
|
}
|
|
266
261
|
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)));
|
|
262
|
+
app.get(paths, (0, import_error_handling.handleErrors)(createViewMiddleware(route, errorRoutes, context, viewHandler), true));
|
|
268
263
|
}
|
|
269
264
|
app.get((0, import_shared_utils.getClientBootstrapConfigurationRoutes)(), (0, import_error_handling.handleErrors)(createConfigMiddleware(routes, context, viewHandler)));
|
|
270
265
|
app.get("/" + app.getRegexWildcard(), (0, import_error_handling.handleErrors)(createNotFoundMiddleware(errorRoutes, context, viewHandler)));
|
|
@@ -299,12 +294,6 @@ function addDefaultLocaleRedirects(defaultLocale, defaultLocalePaths, defaultRed
|
|
|
299
294
|
return res.sendStatus(301);
|
|
300
295
|
});
|
|
301
296
|
}
|
|
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
297
|
function byteSize(body) {
|
|
309
298
|
if (Buffer.isBuffer(body)) {
|
|
310
299
|
return body.length;
|
package/build/es/index.js
CHANGED
|
@@ -91,8 +91,19 @@ async function initContext(appConfig, runtimeEnvironment, globalData) {
|
|
|
91
91
|
return serverContext;
|
|
92
92
|
}
|
|
93
93
|
export class LwrApp {
|
|
94
|
+
app;
|
|
95
|
+
server;
|
|
96
|
+
initialized = false;
|
|
97
|
+
config;
|
|
98
|
+
runtimeEnvironment;
|
|
99
|
+
globalData;
|
|
100
|
+
// generic server API
|
|
101
|
+
serverType;
|
|
102
|
+
use;
|
|
103
|
+
all;
|
|
104
|
+
get;
|
|
105
|
+
post;
|
|
94
106
|
constructor(configs) {
|
|
95
|
-
this.initialized = false;
|
|
96
107
|
const span = getTracer().startSpan({ name: CoreSpan.CreateServer });
|
|
97
108
|
const { appConfig, runtimeEnvironment, globalData } = configs;
|
|
98
109
|
this.config = appConfig;
|
|
@@ -12,17 +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.
|
|
25
|
+
res.send(descriptions.INVALID.INVALID_API_VERSION(req.params.apiVersion, appConfig.apiVersion));
|
|
26
26
|
return;
|
|
27
27
|
}
|
|
28
28
|
const { runtimeEnvironment, runtimeParams } = req.getRuntimeContext(defaultRuntimeEnvironment);
|
|
@@ -65,7 +65,7 @@ function createSourceMapMiddleware(context) {
|
|
|
65
65
|
return async (req, res) => {
|
|
66
66
|
if (!req.validateEnvironmentRequest(appConfig)) {
|
|
67
67
|
res.status(400);
|
|
68
|
-
res.send(descriptions.
|
|
68
|
+
res.send(descriptions.INVALID.INVALID_ENVIRONMENT(req.params.environment));
|
|
69
69
|
return;
|
|
70
70
|
}
|
|
71
71
|
const { runtimeEnvironment } = req.getRuntimeContext(defaultRuntimeEnvironment);
|
|
@@ -5,6 +5,11 @@ import { getRequestProperties } from './utils/request.js';
|
|
|
5
5
|
let hmr;
|
|
6
6
|
const HMR_URI = '/:apiVersion/hmr/:format/:compat';
|
|
7
7
|
class Hmr {
|
|
8
|
+
connectedClients;
|
|
9
|
+
server;
|
|
10
|
+
context;
|
|
11
|
+
// Restriction: HMR only supports format=ESM and bundle=false
|
|
12
|
+
moduleRegistry;
|
|
8
13
|
constructor(server, context) {
|
|
9
14
|
this.server = server;
|
|
10
15
|
this.context = context;
|
|
@@ -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,17 +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.
|
|
24
|
+
res.send(descriptions.INVALID.INVALID_API_VERSION(req.params.apiVersion, appConfig.apiVersion));
|
|
25
25
|
return;
|
|
26
26
|
}
|
|
27
27
|
const { runtimeEnvironment, runtimeParams } = req.getRuntimeContext(defaultRuntimeEnvironment);
|
|
@@ -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,17 +16,24 @@ 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'];
|
|
34
26
|
const protocol = req.protocol;
|
|
27
|
+
const cookieLength = req.headers['cookie']?.length || 0;
|
|
28
|
+
let cookieMsg = `Cookie length: ${cookieLength}`;
|
|
29
|
+
if (cookieLength) {
|
|
30
|
+
cookieMsg += `, Cookie has '__Secure-has-sid': ${!!req.cookie('__Secure-has-sid')}, Cookie has 'sid': ${!!req.cookie('sid')}`;
|
|
31
|
+
}
|
|
35
32
|
// Only Add this log when on MRT. Useful to catch issues where CDN did not send us the right info.
|
|
36
33
|
if (isLambdaEnv()) {
|
|
37
34
|
logger.info({
|
|
38
35
|
label: `request-processor-middleware`,
|
|
39
|
-
message: `Original Url: ${req.originalUrl}, Forwarded: ${forwarded}, X-Forwarded-Proto: ${forwardedProto}, Host: ${host},
|
|
36
|
+
message: `Original Url: ${req.originalUrl}, Forwarded: ${forwarded}, X-Forwarded-Proto: ${forwardedProto}, Host: ${host}, Protocol: ${protocol}, ${cookieMsg}, ${MRT_REQUEST_CLASS}: ${requestClass}, ${TRUE_CLIENT_IP}: ${trueClientIP}, ${CORRELATION_ID}: ${correlationID}, ${REQUEST_DEPTH_HEADER}: ${requestDepth}`,
|
|
40
37
|
});
|
|
41
38
|
}
|
|
42
39
|
}
|
|
@@ -81,7 +78,7 @@ export function requestProcessorMiddleware(app, context) {
|
|
|
81
78
|
else {
|
|
82
79
|
logger.debug({
|
|
83
80
|
label: `request-processor-middleware`,
|
|
84
|
-
message: `${
|
|
81
|
+
message: `${MRT_REQUEST_CLASS} ignored ${req.headers ? req.headers[MRT_REQUEST_CLASS] : 'no-headers'}`,
|
|
85
82
|
});
|
|
86
83
|
req.basePath = basePath;
|
|
87
84
|
}
|
|
@@ -89,12 +86,21 @@ export function requestProcessorMiddleware(app, context) {
|
|
|
89
86
|
await next();
|
|
90
87
|
});
|
|
91
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Parse the basePath passed via the X-Mobify-Request-Class header.
|
|
91
|
+
* Example: basePath=/token
|
|
92
|
+
*
|
|
93
|
+
* basePath: The dynamic base path
|
|
94
|
+
* '' or undefined -> LWR basePath ''
|
|
95
|
+
* token or /token -> LWR basePath '/token'
|
|
96
|
+
*
|
|
97
|
+
*/
|
|
92
98
|
function parseRequestClass(requestClass) {
|
|
93
99
|
// If there is no requestClass do not bother parsing
|
|
94
100
|
if (!requestClass) {
|
|
95
101
|
return {};
|
|
96
102
|
}
|
|
97
|
-
// Split the
|
|
103
|
+
// Split the header into individual key-value pairs
|
|
98
104
|
const keyValuePairs = requestClass.split(';');
|
|
99
105
|
// Create an object to store the parsed values
|
|
100
106
|
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);
|
|
@@ -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,56 @@
|
|
|
1
|
-
import { descriptions, DiagnosticsError,
|
|
1
|
+
import { descriptions, DiagnosticsError, LwrError, LwrInvalidError, LwrStatusError, LwrUnresolvableError, } from '@lwrjs/diagnostics';
|
|
2
2
|
import { logger } from '@lwrjs/diagnostics';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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, isBaseDoc) {
|
|
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
|
+
// if something is missing during base doc generation, the status is 500
|
|
36
|
+
// eg: a bundle cannot be found during SSR -> the page fails with a 500
|
|
37
|
+
status = isBaseDoc ? 500 : 404;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
// catchall: likely a LwrServerError
|
|
41
|
+
body =
|
|
42
|
+
error instanceof LwrError
|
|
43
|
+
? body
|
|
44
|
+
: `${descriptions.SERVER.SERVER_ERROR(req.originalUrl)}: ${body}`;
|
|
6
45
|
}
|
|
7
|
-
if (
|
|
8
|
-
return
|
|
46
|
+
if (debug) {
|
|
47
|
+
// return a debug base doc and a 200 response code if debug mode is on
|
|
48
|
+
body = `<div style="font-family:sans-serif;margin:50px;"><h1>${status}: Document generation failed</h1><p>${body.replace(/</g, '<').replace(/>/g, '>')}</p></div>`;
|
|
49
|
+
status = 200;
|
|
9
50
|
}
|
|
10
|
-
|
|
11
|
-
return { status: 500, message: `${descriptions.SERVER.SERVER_ERROR(url)}: ${error.message}` };
|
|
51
|
+
return { status, body, headers: Object.keys(headers).length > 0 ? headers : undefined };
|
|
12
52
|
}
|
|
13
|
-
export function handleErrors(middleware) {
|
|
53
|
+
export function handleErrors(middleware, isBaseDoc = false) {
|
|
14
54
|
return async (req, res, next) => {
|
|
15
55
|
try {
|
|
16
56
|
await middleware(req, res, next);
|
|
@@ -24,9 +64,11 @@ export function handleErrors(middleware) {
|
|
|
24
64
|
else {
|
|
25
65
|
logger.error(err);
|
|
26
66
|
}
|
|
27
|
-
const { status,
|
|
28
|
-
|
|
29
|
-
|
|
67
|
+
const { status, body, headers } = createReturnStatus(err, req,
|
|
68
|
+
// only return HTML error screen for base doc requests in debug mode
|
|
69
|
+
req.query.debug !== undefined && isBaseDoc, isBaseDoc);
|
|
70
|
+
headers && res.set(headers);
|
|
71
|
+
res.status(status).send(body);
|
|
30
72
|
}
|
|
31
73
|
};
|
|
32
74
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { explodeSpecifier, explodeSpecifiers, LATEST_SIGNATURE } from '@lwrjs/shared-utils';
|
|
2
|
-
import { descriptions,
|
|
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 new
|
|
9
|
+
throw new LwrInvalidError(descriptions.INVALID.INVALID_SPECIFIER(specifier));
|
|
10
10
|
}
|
|
11
11
|
const moduleId = explodeSpecifier(specifier);
|
|
12
12
|
return {
|
|
@@ -30,7 +30,7 @@ export function getMappingIdentity(req) {
|
|
|
30
30
|
export function getResourceIdentity(req) {
|
|
31
31
|
const { specifier, signature = LATEST_SIGNATURE } = req.params;
|
|
32
32
|
if (validateSpecifier(specifier) === false) {
|
|
33
|
-
throw new
|
|
33
|
+
throw new LwrInvalidError(descriptions.INVALID.INVALID_SPECIFIER(specifier));
|
|
34
34
|
}
|
|
35
35
|
const resourceId = explodeSpecifier(specifier);
|
|
36
36
|
return {
|
|
@@ -46,7 +46,7 @@ export function getAssetIdentity(req) {
|
|
|
46
46
|
: '/' + req.params[0]
|
|
47
47
|
: req.originalUrl.split('?')[0];
|
|
48
48
|
if (validateSpecifier(specifier) === false) {
|
|
49
|
-
throw new
|
|
49
|
+
throw new LwrInvalidError(descriptions.INVALID.INVALID_SPECIFIER(specifier));
|
|
50
50
|
}
|
|
51
51
|
return {
|
|
52
52
|
immutable,
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { TextEncoder } from 'util';
|
|
2
1
|
import { URLSearchParams } from 'url';
|
|
2
|
+
import { TextEncoder } from 'util';
|
|
3
|
+
import { brotliCompressSync, gzipSync } from 'zlib';
|
|
3
4
|
import { descriptions, logger } from '@lwrjs/diagnostics';
|
|
5
|
+
import { RequestHandlerSpan, getTraceCollector, getTracer } from '@lwrjs/instrumentation';
|
|
4
6
|
import { getClientRoutes } from '@lwrjs/router';
|
|
5
|
-
import { decodeViewPath, extractRequestParams, getClientBootstrapConfigurationRoutes,
|
|
6
|
-
import { RequestHandlerSpan, getTracer } from '@lwrjs/instrumentation';
|
|
7
|
-
import { handleErrors } from './utils/error-handling.js';
|
|
7
|
+
import { CORRELATION_ID, TRUE_CLIENT_IP, decodeViewPath, extractRequestParams, getClientBootstrapConfigurationRoutes, getTraceHeaders, isLambdaEnv, isLocalDev, shortestTtl, isLocalAuthEnabled, isLocalPreview, } from '@lwrjs/shared-utils';
|
|
8
8
|
import { LwrViewHandler } from '@lwrjs/view-registry';
|
|
9
|
-
import { getTraceCollector } from '@lwrjs/instrumentation';
|
|
10
|
-
import { brotliCompressSync, gzipSync } from 'zlib';
|
|
11
9
|
import { getMrtCompressionThreshold } from './utils/compression.js';
|
|
10
|
+
import { handleErrors } from './utils/error-handling.js';
|
|
12
11
|
function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
13
12
|
const errorRoute = errorRoutes.find((route) => route.status === 500);
|
|
14
13
|
const appConfig = context.appConfig;
|
|
@@ -17,12 +16,12 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
17
16
|
return async (req, res) => {
|
|
18
17
|
if (!req.validateEnvironmentRequest(appConfig)) {
|
|
19
18
|
res.status(400);
|
|
20
|
-
res.send(descriptions.
|
|
19
|
+
res.send(descriptions.INVALID.INVALID_ENVIRONMENT(req.params.environment));
|
|
21
20
|
return;
|
|
22
21
|
}
|
|
23
22
|
if (!req.validateJsonRequest()) {
|
|
24
23
|
res.status(400);
|
|
25
|
-
res.send(descriptions.
|
|
24
|
+
res.send(descriptions.INVALID.INVALID_JSON());
|
|
26
25
|
return;
|
|
27
26
|
}
|
|
28
27
|
const { runtimeEnvironment, runtimeParams: defaultRuntimeParams } = req.getRuntimeContext(context.runtimeEnvironment);
|
|
@@ -43,13 +42,15 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
43
42
|
params: viewRequest.params,
|
|
44
43
|
query: viewRequest.query,
|
|
45
44
|
cookie: req.headers?.cookie,
|
|
46
|
-
trueClientIP: req.headers
|
|
45
|
+
trueClientIP: req.headers?.[TRUE_CLIENT_IP],
|
|
46
|
+
correlationID: req.headers?.[CORRELATION_ID],
|
|
47
47
|
coreProxy: req.getCoreProxy(appConfig.coreProxy ?? undefined, route.bootstrap?.proxyForSSR),
|
|
48
48
|
};
|
|
49
49
|
const resolve = req.isJsonRequest() ? viewHandler.getViewJson : viewHandler.getViewContent;
|
|
50
50
|
let viewResponse;
|
|
51
51
|
let resolvedRoute;
|
|
52
52
|
let traceId;
|
|
53
|
+
let headers = {};
|
|
53
54
|
try {
|
|
54
55
|
viewResponse = await getTracer().trace({
|
|
55
56
|
name: RequestHandlerSpan.GetView,
|
|
@@ -61,7 +62,9 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
61
62
|
locale: runtimeParams.locale,
|
|
62
63
|
},
|
|
63
64
|
}, async (span) => {
|
|
65
|
+
runtimeParams.viewSpanID = span.spanId;
|
|
64
66
|
traceId = span.traceId;
|
|
67
|
+
headers = getTraceHeaders(runtimeParams, span);
|
|
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,9 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
89
94
|
resolvedRoute = errorRoute;
|
|
90
95
|
}
|
|
91
96
|
finally {
|
|
97
|
+
if (Object.keys(headers).length)
|
|
98
|
+
res.set(headers);
|
|
92
99
|
if (traceId?.length) {
|
|
93
|
-
res.setHeader('x-trace-id', traceId);
|
|
94
100
|
res.set({
|
|
95
101
|
'Server-Timing': getTraceCollector().getSpansInTrace(traceId),
|
|
96
102
|
});
|
|
@@ -102,6 +108,16 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
102
108
|
}
|
|
103
109
|
// view response will be html by default
|
|
104
110
|
res.type('text/html');
|
|
111
|
+
// Add a custom auth cookie to the browser for all view requests during local dev / local preview
|
|
112
|
+
if (isLocalDev() || isLocalPreview()) {
|
|
113
|
+
if (isLocalAuthEnabled()) {
|
|
114
|
+
res.setHeader('Set-Cookie', 'LocalAuthenticationEnabled=1;');
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
// When running locally, expire the previously set cookie if we are previewing with the guest user or no auth token
|
|
118
|
+
res.setHeader('Set-Cookie', 'LocalAuthenticationEnabled=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT;');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
105
121
|
// the default content type can be overridden if specified by the view response
|
|
106
122
|
if (viewResponse.headers) {
|
|
107
123
|
if (isLocalDev()) {
|
|
@@ -119,29 +135,10 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
119
135
|
}
|
|
120
136
|
}
|
|
121
137
|
let status = resolvedRoute.status || viewResponse.status || 200;
|
|
122
|
-
const viewDefinitionStatus = viewResponse.metadata?.viewDefinition?.status;
|
|
123
138
|
if (viewResponse.status === 301 || viewResponse.status === 302) {
|
|
124
139
|
// route handle redirect status takes precedence
|
|
125
140
|
status = viewResponse.status;
|
|
126
141
|
}
|
|
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
142
|
res.status(status);
|
|
146
143
|
// LWR@MRT 254 temporary safeguard for "dupe styles" issue causing huge base docs
|
|
147
144
|
// Re-evaluate for removal once we determine it is no longer needed: W-17201070
|
|
@@ -272,7 +269,7 @@ export function viewMiddleware(app, context) {
|
|
|
272
269
|
}
|
|
273
270
|
}
|
|
274
271
|
logger.debug({ label: `view-middleware`, message: `Add view paths ${paths}` });
|
|
275
|
-
app.get(paths, handleErrors(createViewMiddleware(route, errorRoutes, context, viewHandler)));
|
|
272
|
+
app.get(paths, handleErrors(createViewMiddleware(route, errorRoutes, context, viewHandler), true));
|
|
276
273
|
}
|
|
277
274
|
// create and attach middleware for bootstrap configurations
|
|
278
275
|
app.get(getClientBootstrapConfigurationRoutes(), handleErrors(createConfigMiddleware(routes, context, viewHandler)));
|
|
@@ -325,14 +322,6 @@ function addDefaultLocaleRedirects(defaultLocale, defaultLocalePaths, defaultRed
|
|
|
325
322
|
return res.sendStatus(301);
|
|
326
323
|
});
|
|
327
324
|
}
|
|
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
325
|
// Get number of bytes from a string. Different char encodings can effect size per char.
|
|
337
326
|
function byteSize(body) {
|
|
338
327
|
if (Buffer.isBuffer(body)) {
|
|
@@ -847,6 +847,8 @@ export default class SiteGenerator {
|
|
|
847
847
|
}
|
|
848
848
|
// Class used to track import metadata for a view
|
|
849
849
|
export class ViewImportMetadataImpl {
|
|
850
|
+
existing;
|
|
851
|
+
additional;
|
|
850
852
|
constructor(existingImportMetadata, additionalImportMetadata) {
|
|
851
853
|
this.existing = existingImportMetadata;
|
|
852
854
|
this.additional = additionalImportMetadata || { imports: {}, index: {} };
|
|
@@ -3,6 +3,9 @@ import https from 'https';
|
|
|
3
3
|
import { logger } from '@lwrjs/diagnostics';
|
|
4
4
|
import { isLocalDev, isModuleOrBundleUrl } from '@lwrjs/shared-utils';
|
|
5
5
|
export default class NetworkDispatcher {
|
|
6
|
+
port;
|
|
7
|
+
internalRequestKey;
|
|
8
|
+
pool;
|
|
6
9
|
constructor(port, internalRequestKey) {
|
|
7
10
|
this.port = port || 3000;
|
|
8
11
|
const httpClient = this.port == 443 ? https : http;
|
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.31",
|
|
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.31",
|
|
47
|
+
"@lwrjs/asset-registry": "0.17.2-alpha.31",
|
|
48
|
+
"@lwrjs/asset-transformer": "0.17.2-alpha.31",
|
|
49
|
+
"@lwrjs/base-view-provider": "0.17.2-alpha.31",
|
|
50
|
+
"@lwrjs/base-view-transformer": "0.17.2-alpha.31",
|
|
51
|
+
"@lwrjs/client-modules": "0.17.2-alpha.31",
|
|
52
|
+
"@lwrjs/config": "0.17.2-alpha.31",
|
|
53
|
+
"@lwrjs/diagnostics": "0.17.2-alpha.31",
|
|
54
|
+
"@lwrjs/esbuild": "0.17.2-alpha.31",
|
|
55
|
+
"@lwrjs/fs-asset-provider": "0.17.2-alpha.31",
|
|
56
|
+
"@lwrjs/fs-watch": "0.17.2-alpha.31",
|
|
57
|
+
"@lwrjs/html-view-provider": "0.17.2-alpha.31",
|
|
58
|
+
"@lwrjs/instrumentation": "0.17.2-alpha.31",
|
|
59
|
+
"@lwrjs/loader": "0.17.2-alpha.31",
|
|
60
|
+
"@lwrjs/lwc-module-provider": "0.17.2-alpha.31",
|
|
61
|
+
"@lwrjs/lwc-ssr": "0.17.2-alpha.31",
|
|
62
|
+
"@lwrjs/markdown-view-provider": "0.17.2-alpha.31",
|
|
63
|
+
"@lwrjs/module-bundler": "0.17.2-alpha.31",
|
|
64
|
+
"@lwrjs/module-registry": "0.17.2-alpha.31",
|
|
65
|
+
"@lwrjs/npm-module-provider": "0.17.2-alpha.31",
|
|
66
|
+
"@lwrjs/nunjucks-view-provider": "0.17.2-alpha.31",
|
|
67
|
+
"@lwrjs/o11y": "0.17.2-alpha.31",
|
|
68
|
+
"@lwrjs/resource-registry": "0.17.2-alpha.31",
|
|
69
|
+
"@lwrjs/router": "0.17.2-alpha.31",
|
|
70
|
+
"@lwrjs/server": "0.17.2-alpha.31",
|
|
71
|
+
"@lwrjs/shared-utils": "0.17.2-alpha.31",
|
|
72
|
+
"@lwrjs/static": "0.17.2-alpha.31",
|
|
73
|
+
"@lwrjs/view-registry": "0.17.2-alpha.31",
|
|
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.31",
|
|
84
84
|
"@types/ws": "^8.5.12",
|
|
85
85
|
"memfs": "^4.13.0"
|
|
86
86
|
},
|
|
@@ -88,10 +88,10 @@
|
|
|
88
88
|
"lwc": ">= 2.x"
|
|
89
89
|
},
|
|
90
90
|
"engines": {
|
|
91
|
-
"node": ">=
|
|
91
|
+
"node": ">=20.0.0"
|
|
92
92
|
},
|
|
93
93
|
"volta": {
|
|
94
94
|
"extends": "../../../package.json"
|
|
95
95
|
},
|
|
96
|
-
"gitHead": "
|
|
96
|
+
"gitHead": "bbb087ab080321047b10bbcda40e88e69b6a69a5"
|
|
97
97
|
}
|