@lwrjs/dev-proxy-server 0.15.4 → 0.15.6

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.
@@ -38,14 +38,33 @@ var ProxyLogLevels;
38
38
  ProxyLogLevels2["Error"] = "error";
39
39
  ProxyLogLevels2["Silent"] = "silent";
40
40
  })(ProxyLogLevels || (ProxyLogLevels = {}));
41
+ var PROXY_URL_REGEX = /^([a-z][a-z0-9+\-.]*):\/\/([^/]+)/i;
41
42
  function getForwardedHeader(incomingRequest, remoteOrigin) {
42
- const remoteHost = remoteOrigin?.replace(/^([a-z][a-z0-9+\-.]*):\/\//, "");
43
- const hostHeader = remoteHost || incomingRequest.headers.host;
44
- const hostProto = remoteHost ? "https" : incomingRequest.protocol;
45
- return `host=${hostHeader};proto=${hostProto}`;
43
+ const {host: remoteHost, proto: remoteProto} = remoteOrigin ? parseHostAndProto(remoteOrigin) : {host: void 0, proto: void 0};
44
+ const host = remoteHost ?? incomingRequest.headers.host;
45
+ const proto = remoteProto ?? incomingRequest.protocol;
46
+ return `host=${host};proto=${proto}`;
47
+ }
48
+ function parseHostAndProto(urlString) {
49
+ if (!urlString) {
50
+ return {};
51
+ }
52
+ const match = PROXY_URL_REGEX.exec(urlString);
53
+ if (match) {
54
+ const [, proto, host] = match;
55
+ return {proto, host};
56
+ }
57
+ import_diagnostics.logger.warn({
58
+ label: "dev-proxy-server",
59
+ message: `Invalid remoteOrigin format: ${urlString}`
60
+ });
61
+ return {
62
+ host: urlString,
63
+ proto: "https"
64
+ };
46
65
  }
47
66
  function addLocalProxyMiddleware(app, defaultHost, remoteOrigin) {
48
- const domainAndPort = defaultHost.replace(/^([a-z][a-z0-9+\-.]*):\/\//, "");
67
+ const domainAndPort = parseHostAndProto(defaultHost).host;
49
68
  app.use("/", (0, import_http_proxy_middleware.createProxyMiddleware)({
50
69
  target: defaultHost,
51
70
  changeOrigin: true,
@@ -67,7 +86,7 @@ function addRemoteProxyMiddleware(app, proxyConfig) {
67
86
  const {proxyConfigs} = proxyConfig;
68
87
  for (const entry of proxyConfigs) {
69
88
  const [path, target] = entry;
70
- const targetHost = target.replace(/^([a-z][a-z0-9+\-.]*):\/\//, "");
89
+ const targetHost = parseHostAndProto(target).host;
71
90
  const pathRewrite = mobifyRules && (path.indexOf("/mobify/proxy") === 0 || path.indexOf("/mobify/caching") === 0) ? {[path]: ""} : void 0;
72
91
  app.use(path, (0, import_http_proxy_middleware.createProxyMiddleware)({
73
92
  target,
@@ -85,7 +104,7 @@ function addRemoteProxyMiddleware(app, proxyConfig) {
85
104
  if (hostHeader !== target) {
86
105
  proxyRequest.setHeader(HOST, targetHost);
87
106
  }
88
- proxyRequest.setHeader("Forwarded", `host=${hostHeader}`);
107
+ proxyRequest.setHeader("Forwarded", getForwardedHeader(incomingRequest));
89
108
  const originalPath = incomingRequest.url;
90
109
  proxyRequest.path = originalPath;
91
110
  if (process.env.AUTH_TOKEN) {
@@ -1,15 +1,21 @@
1
1
  import type { Application as ExpressApp } from 'express';
2
2
  import type { LwrProxyConfiguration } from './proxy-server.js';
3
3
  /**
4
- * The Proxy middleware responsible for proxying all other requests not configured to external systems.
5
- * @param app
6
- * @param defaultHost
4
+ * Proxy middleware for handling requests that are served by the LWR server or lambda.
5
+ *
6
+ * @param app - The Express app instance to which the middleware is attached.
7
+ * @param defaultHost - A URL string pointing to the local proxy server for handling requests.
8
+ * @param remoteOrigin - A URL string representing the value of the first entry in the `_proxy` configuration file.
7
9
  */
8
10
  export declare function addLocalProxyMiddleware(app: ExpressApp, defaultHost: string, remoteOrigin?: string): void;
9
11
  /**
10
- * The Proxy middleware responsible for proxying requests to a configured remote origin.
11
- * @param app
12
- * @param proxyConfig
12
+ * Middleware to handle API request proxying to a configured remote origin.
13
+ *
14
+ * This middleware forwards API requests to the specified remote origin
15
+ * as defined in the proxy configuration.
16
+ *
17
+ * @param app - The Express app instance to which the middleware is attached.
18
+ * @param proxyConfig - Configuration details initialized when the proxy server starts.
13
19
  */
14
20
  export declare function addRemoteProxyMiddleware(app: ExpressApp, proxyConfig: LwrProxyConfiguration): void;
15
21
  //# sourceMappingURL=middleware.d.ts.map
@@ -11,31 +11,90 @@ var ProxyLogLevels;
11
11
  ProxyLogLevels["Error"] = "error";
12
12
  ProxyLogLevels["Silent"] = "silent";
13
13
  })(ProxyLogLevels || (ProxyLogLevels = {}));
14
+ // Regular expression to extract the protocol and host from a remote proxy URL.
15
+ // Example matches:
16
+ // Input: "https://example.com/path"
17
+ // Matches: ["https://example.com", "https", "example.com"]
18
+ // Explanation:
19
+ // ^ - Match the start of the string.
20
+ // ([a-z][a-z0-9+\-.]*) - Capture the protocol (e.g., "http", "https"), which must start with a letter and may include alphanumeric characters, "+", "-", or ".".
21
+ // :\/\/ - Match "://" to separate the protocol from the host.
22
+ // ([^/]+) - Capture the host (everything until the first "/" or end of string).
23
+ // i - Case-insensitive flag.
24
+ const PROXY_URL_REGEX = /^([a-z][a-z0-9+\-.]*):\/\/([^/]+)/i;
25
+ /**
26
+ * Constructs the `Forwarded` header value for an HTTP request.
27
+ *
28
+ * In a production environment, this header is usually added by the CDN and references the configured site domain URL.
29
+ * This function allows for customization by optionally overriding the protocol and host with a remote origin.
30
+ *
31
+ * @param incomingRequest - The incoming HTTP request object, contains details about the original express request.
32
+ * @param remoteOrigin - Optional. A remote origin URL to override the default protocol and host values.
33
+ * @returns The constructed `Forwarded` header string.
34
+ */
14
35
  function getForwardedHeader(incomingRequest, remoteOrigin) {
15
- // In prod, the Forwarded header is added by the CDN and is set to the Core org
16
- const remoteHost = remoteOrigin?.replace(/^([a-z][a-z0-9+\-.]*):\/\//, '');
17
- const hostHeader = remoteHost || incomingRequest.headers.host;
18
- const hostProto = remoteHost ? 'https' : incomingRequest.protocol;
19
- return `host=${hostHeader};proto=${hostProto}`;
36
+ const { host: remoteHost, proto: remoteProto } = remoteOrigin
37
+ ? parseHostAndProto(remoteOrigin)
38
+ : { host: undefined, proto: undefined };
39
+ const host = remoteHost ?? incomingRequest.headers.host;
40
+ const proto = remoteProto ?? incomingRequest.protocol;
41
+ return `host=${host};proto=${proto}`;
42
+ }
43
+ /**
44
+ * Parses the protocol and host from a given URL string.
45
+ *
46
+ * If the URL matches the expected format, it extracts the protocol and host.
47
+ * If the URL is invalid, it logs a warning and returns a default protocol (`https`)
48
+ * and the original string as the host.
49
+ *
50
+ * @param urlString - The URL string to parse.
51
+ * @returns An object containing `proto` (protocol) and `host` values.
52
+ * If the URL is invalid, a default protocol (`https`) and the original
53
+ * string as the host are returned.
54
+ */
55
+ function parseHostAndProto(urlString) {
56
+ if (!urlString) {
57
+ return {};
58
+ }
59
+ const match = PROXY_URL_REGEX.exec(urlString);
60
+ if (match) {
61
+ const [, proto, host] = match;
62
+ return { proto, host };
63
+ }
64
+ logger.warn({
65
+ label: 'dev-proxy-server',
66
+ message: `Invalid remoteOrigin format: ${urlString}`,
67
+ });
68
+ return {
69
+ host: urlString,
70
+ proto: 'https',
71
+ };
20
72
  }
21
73
  /**
22
- * The Proxy middleware responsible for proxying all other requests not configured to external systems.
23
- * @param app
24
- * @param defaultHost
74
+ * Proxy middleware for handling requests that are served by the LWR server or lambda.
75
+ *
76
+ * @param app - The Express app instance to which the middleware is attached.
77
+ * @param defaultHost - A URL string pointing to the local proxy server for handling requests.
78
+ * @param remoteOrigin - A URL string representing the value of the first entry in the `_proxy` configuration file.
25
79
  */
26
80
  export function addLocalProxyMiddleware(app, defaultHost, remoteOrigin) {
27
- const domainAndPort = defaultHost.replace(/^([a-z][a-z0-9+\-.]*):\/\//, '');
81
+ // Extract the domain and port from the defaultHost URL string.
82
+ const domainAndPort = parseHostAndProto(defaultHost).host;
28
83
  app.use('/', createProxyMiddleware({
29
84
  target: defaultHost,
30
85
  changeOrigin: true,
31
86
  onProxyReq: (proxyRequest, incomingRequest) => {
32
87
  // Set the Host header to the target
33
88
  const hostHeader = incomingRequest.headers.host;
89
+ // This will be any time we have a proxy config
34
90
  if (hostHeader !== domainAndPort) {
91
+ // Setting the Host Header to the domain and port for the proxy server URL
35
92
  proxyRequest.setHeader(HOST, domainAndPort);
36
- // Set the Forwarded header if it's not defined
93
+ // Add the `Forwarded` header if it is not already set.
37
94
  const forwarded = incomingRequest.headers.forwarded;
38
- proxyRequest.setHeader('Forwarded', forwarded ? forwarded : getForwardedHeader(incomingRequest, remoteOrigin));
95
+ proxyRequest.setHeader('Forwarded',
96
+ // Set the `Forwarded` header using the first entry from the proxy configuration.
97
+ forwarded ? forwarded : getForwardedHeader(incomingRequest, remoteOrigin));
39
98
  // Add auth token to cookies; used in the fetchController during local preview
40
99
  if (process.env.AUTH_TOKEN && !proxyRequest.path.startsWith('/mobify/bundle/')) {
41
100
  addAuthCookie(proxyRequest, process.env.AUTH_TOKEN);
@@ -45,17 +104,21 @@ export function addLocalProxyMiddleware(app, defaultHost, remoteOrigin) {
45
104
  }));
46
105
  }
47
106
  /**
48
- * The Proxy middleware responsible for proxying requests to a configured remote origin.
49
- * @param app
50
- * @param proxyConfig
107
+ * Middleware to handle API request proxying to a configured remote origin.
108
+ *
109
+ * This middleware forwards API requests to the specified remote origin
110
+ * as defined in the proxy configuration.
111
+ *
112
+ * @param app - The Express app instance to which the middleware is attached.
113
+ * @param proxyConfig - Configuration details initialized when the proxy server starts.
51
114
  */
52
115
  export function addRemoteProxyMiddleware(app, proxyConfig) {
53
116
  const mobifyRules = process.env.ADD_MOBIFY_PROXY_RULES === 'true';
54
117
  const { proxyConfigs } = proxyConfig;
55
118
  for (const entry of proxyConfigs) {
56
119
  const [path, target] = entry;
57
- // remove the scheme from the proxyConfig host.
58
- const targetHost = target.replace(/^([a-z][a-z0-9+\-.]*):\/\//, '');
120
+ // Extract the domain and port from the API target URL string.
121
+ const targetHost = parseHostAndProto(target).host;
59
122
  // TODO: Ask Commerce if this rewrite logic can be removed
60
123
  // Needed for commerce local-dev when running MRT bundles without a configured Cloudflare CDN
61
124
  // Rewrites /mobify/proxy/core and /mobify/caching/core paths (this is what pwa-kit does)
@@ -82,7 +145,8 @@ export function addRemoteProxyMiddleware(app, proxyConfig) {
82
145
  proxyRequest.setHeader(HOST, targetHost);
83
146
  }
84
147
  // Add Forwarded header per https://git.soma.salesforce.com/pages/benjamin-fry/lwr-on-mrt-designs/request_path.html
85
- proxyRequest.setHeader('Forwarded', `host=${hostHeader}`);
148
+ // Based on the incoming request's host and protocol. Is this necessary for API calls?
149
+ proxyRequest.setHeader('Forwarded', getForwardedHeader(incomingRequest));
86
150
  // Preserve the original path, including double slashes
87
151
  const originalPath = incomingRequest.url;
88
152
  proxyRequest.path = originalPath;
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
- "version": "0.15.4",
7
+ "version": "0.15.6",
8
8
  "homepage": "https://developer.salesforce.com/docs/platform/lwr/overview",
9
9
  "repository": {
10
10
  "type": "git",
@@ -33,13 +33,13 @@
33
33
  "build": "tsc -b"
34
34
  },
35
35
  "dependencies": {
36
- "@lwrjs/diagnostics": "0.15.4",
37
- "@lwrjs/shared-utils": "0.15.4",
36
+ "@lwrjs/diagnostics": "0.15.6",
37
+ "@lwrjs/shared-utils": "0.15.6",
38
38
  "express": "^4.20.0",
39
39
  "http-proxy-middleware": "2.0.7"
40
40
  },
41
41
  "devDependencies": {
42
- "@lwrjs/types": "0.15.4"
42
+ "@lwrjs/types": "0.15.6"
43
43
  },
44
44
  "engines": {
45
45
  "node": ">=18.0.0"
@@ -47,5 +47,5 @@
47
47
  "volta": {
48
48
  "extends": "../../../package.json"
49
49
  },
50
- "gitHead": "7e461b5d43aeaf5adce95b2ab8fec57748c4fa07"
50
+ "gitHead": "149a9606a77347eb0ba326497f8fcde5c855d5f8"
51
51
  }