@salesforce/pwa-kit-runtime 4.0.0-extensibility-preview.1 → 4.0.0-extensibility-preview.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/pwa-kit-runtime",
3
- "version": "4.0.0-extensibility-preview.1",
3
+ "version": "4.0.0-extensibility-preview.3",
4
4
  "description": "The PWAKit Runtime",
5
5
  "homepage": "https://github.com/SalesforceCommerceCloud/pwa-kit/tree/develop/packages/pwa-kit-runtime#readme",
6
6
  "bugs": {
@@ -46,13 +46,13 @@
46
46
  },
47
47
  "devDependencies": {
48
48
  "@loadable/component": "^5.15.3",
49
- "@salesforce/pwa-kit-dev": "4.0.0-extensibility-preview.1",
50
- "@salesforce/pwa-kit-extension-sdk": "4.0.0-extensibility-preview.1",
49
+ "@salesforce/pwa-kit-dev": "4.0.0-extensibility-preview.3",
50
+ "@salesforce/pwa-kit-extension-sdk": "4.0.0-extensibility-preview.3",
51
51
  "@serverless/event-mocks": "^1.1.1",
52
52
  "@types/express": "^4.17.21",
53
53
  "aws-lambda-mock-context": "^3.2.1",
54
54
  "fs-extra": "^11.1.1",
55
- "internal-lib-build": "4.0.0-extensibility-preview.1",
55
+ "internal-lib-build": "4.0.0-extensibility-preview.3",
56
56
  "nock": "^13.3.0",
57
57
  "nodemon": "^2.0.22",
58
58
  "sinon": "^13.0.2",
@@ -60,7 +60,7 @@
60
60
  "supertest": "^4.0.2"
61
61
  },
62
62
  "peerDependencies": {
63
- "@salesforce/pwa-kit-dev": "4.0.0-extensibility-preview.1"
63
+ "@salesforce/pwa-kit-dev": "4.0.0-extensibility-preview.3"
64
64
  },
65
65
  "peerDependenciesMeta": {
66
66
  "@salesforce/pwa-kit-dev": {
@@ -74,5 +74,5 @@
74
74
  "publishConfig": {
75
75
  "directory": "dist"
76
76
  },
77
- "gitHead": "5728f89cb53ab1b0c89418578f3e90c755efb0f8"
77
+ "gitHead": "904de01e826117febeea952e034478349e16ea4d"
78
78
  }
@@ -74,6 +74,11 @@ export namespace RemoteServerFactory {
74
74
  * @private
75
75
  */
76
76
  function _addSDKInternalHandlers(app: any): void;
77
+ /**
78
+ * Set x-forward-* headers into locals, this is primarily used to facilitate react sdk hook `useOrigin`
79
+ * @private
80
+ */
81
+ function _setForwardedHeaders(app: any, options: any): void;
77
82
  /**
78
83
  * @private
79
84
  */
@@ -156,7 +161,7 @@ export namespace RemoteServerFactory {
156
161
  * @param app {Express} - an Express App
157
162
  * @private
158
163
  */
159
- function _createHandler(app: Express): {
164
+ function _createHandler(app: Express, options: any): {
160
165
  handler: (event: any, context: any, callback: any) => void;
161
166
  server: any;
162
167
  app: Express;
@@ -1 +1 @@
1
- {"version":3,"file":"build-remote-server.d.ts","sourceRoot":"","sources":["../../../src/ssr/server/build-remote-server.js"],"names":[],"mappings":"AAoEA;;;;GAIG;AACH,gDAKC;;IAWG;;OAEG;IACH,uCAgFC;IAED;;OAEG;IAEH,gDAEC;IAED;;OAEG;IAEH,iDAEC;IAED;;OAEG;IAEH,4CAEC;IAED;;OAEG;IACH,uDAEC;IAED;;OAEG;IAEH,2CAEC;IAED;;OAEG;IACH,6CAEC;IAED;;OAEG;IACH,4DAIC;IAED;;OAEG;IAEH,yCAEC;IAED;;OAEG;IAEH,uCA6CC;IAED;;;OAGG;IACH,uCAcC;IAED;;OAEG;IAEH,+CAEC;IAED;;OAEG;IACH,kDAEC;IAED;;OAEG;IACH,oDAEC;IAED;;OAEG;IACH,+EA0CC;IAED;;OAEG;IACH,sFAyDC;IAED;;OAEG;IAEH,iDAEC;IAED;;OAEG;IACH,6DAwLC;IAED;;OAEG;IAEH,sDAOC;IAED;;OAEG;IACH,yDAOC;IAED;;OAEG;IACH,oEAuEC;IAED;;OAEG;IACH,2CAIC;IAED;;OAEG;IACH,8DAaC;IAED;;OAEG;IACH,oDA0EC;IAED;;OAEG;IACH,wCAEC;IAED;;OAEG;IACH,gDAGC;IAED;;;;;;;;;;;OAWG;IACH,sDAwBC;IAED;;;;;;;OAOG;IACH,wFAKC;IAED;;OAEG;IACH,4FASC;IAED;;;;;;;;;;OAUG;IACH,6DAWC;IAED;;;;;;;OAOG;IACH;;;;MA8EC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH;;;;;;;;;;;;MAKC;IAED;;OAEG;IAEH,8CAEC;;AAyFE,uDASN"}
1
+ {"version":3,"file":"build-remote-server.d.ts","sourceRoot":"","sources":["../../../src/ssr/server/build-remote-server.js"],"names":[],"mappings":"AAqEA;;;;GAIG;AACH,gDAKC;;IAWG;;OAEG;IACH,uCAgFC;IAED;;OAEG;IAEH,gDAEC;IAED;;OAEG;IAEH,iDAEC;IAED;;OAEG;IAEH,4CAEC;IAED;;OAEG;IACH,uDAEC;IAED;;OAEG;IAEH,2CAEC;IAED;;OAEG;IACH,6CAEC;IAED;;OAEG;IACH,4DAIC;IAED;;OAEG;IAEH,yCAEC;IAED;;OAEG;IAEH,uCA6CC;IAED;;;OAGG;IACH,uCAcC;IAED;;OAEG;IAEH,+CAEC;IAED;;OAEG;IACH,kDAEC;IAED;;OAEG;IACH,oDAEC;IAED;;OAEG;IACH,+EA2CC;IAED;;OAEG;IACH,sFAyDC;IAED;;OAEG;IAEH,iDAEC;IAED;;;OAGG;IACH,4DAWC;IAED;;OAEG;IACH,6DAwLC;IAED;;OAEG;IAEH,sDAOC;IAED;;OAEG;IACH,yDAOC;IAED;;OAEG;IACH,oEA4EC;IAED;;OAEG;IACH,2CAIC;IAED;;OAEG;IACH,8DAiBC;IAED;;OAEG;IACH,oDA0EC;IAED;;OAEG;IACH,wCAEC;IAED;;OAEG;IACH,gDAGC;IAED;;;;;;;;;;;OAWG;IACH,sDAwBC;IAED;;;;;;;OAOG;IACH,wFAKC;IAED;;OAEG;IACH,4FASC;IAED;;;;;;;;;;OAUG;IACH,6DAWC;IAED;;;;;;;OAOG;IACH;;;;MAgGC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH;;;;;;;;;;;;MAKC;IAED;;OAEG;IAEH,8CAEC;;AA2HE,uDASN"}
@@ -297,6 +297,7 @@ const RemoteServerFactory = exports.RemoteServerFactory = {
297
297
  // want request-processors applied to development views.
298
298
  this._addSDKInternalHandlers(app);
299
299
  this._setupSSRRequestProcessorMiddleware(app);
300
+ this._setForwardedHeaders(app, options);
300
301
  this._setupLogging(app);
301
302
  this._setupMetricsFlushing(app);
302
303
  this._setupHealthcheck(app);
@@ -371,6 +372,22 @@ const RemoteServerFactory = exports.RemoteServerFactory = {
371
372
  _addSDKInternalHandlers(app) {
372
373
  // This method is used by the dev server, but is not needed here.
373
374
  },
375
+ /**
376
+ * Set x-forward-* headers into locals, this is primarily used to facilitate react sdk hook `useOrigin`
377
+ * @private
378
+ */
379
+ _setForwardedHeaders(app, options) {
380
+ app.use((req, res, next) => {
381
+ var _req$headers, _req$headers2;
382
+ const xForwardedHost = (_req$headers = req.headers) === null || _req$headers === void 0 ? void 0 : _req$headers['x-forwarded-host'];
383
+ const xForwardedProto = (_req$headers2 = req.headers) === null || _req$headers2 === void 0 ? void 0 : _req$headers2['x-forwarded-proto'];
384
+ if (xForwardedHost) {
385
+ // prettier-ignore
386
+ res.locals.xForwardedOrigin = `${xForwardedProto || options.protocol}://${xForwardedHost}`;
387
+ }
388
+ next();
389
+ });
390
+ },
374
391
  /**
375
392
  * @private
376
393
  */
@@ -584,7 +601,7 @@ const RemoteServerFactory = exports.RemoteServerFactory = {
584
601
  [_ssrNamespacePaths.slasPrivateProxyPath]: ''
585
602
  },
586
603
  onProxyReq: (proxyRequest, incomingRequest) => {
587
- var _incomingRequest$path;
604
+ var _incomingRequest$path, _incomingRequest$path2;
588
605
  (0, _configureProxy.applyProxyRequestHeaders)({
589
606
  proxyRequest,
590
607
  incomingRequest,
@@ -603,6 +620,11 @@ const RemoteServerFactory = exports.RemoteServerFactory = {
603
620
  if ((_incomingRequest$path = incomingRequest.path) !== null && _incomingRequest$path !== void 0 && _incomingRequest$path.match(options.applySLASPrivateClientToEndpoints)) {
604
621
  proxyRequest.setHeader('Authorization', `Basic ${encodedSlasCredentials}`);
605
622
  }
623
+
624
+ // /oauth2/trusted-agent/token endpoint requires a different auth header
625
+ if ((_incomingRequest$path2 = incomingRequest.path) !== null && _incomingRequest$path2 !== void 0 && _incomingRequest$path2.match(/\/oauth2\/trusted-agent\/token/)) {
626
+ proxyRequest.setHeader('_sfdc_client_auth', encodedSlasCredentials);
627
+ }
606
628
  },
607
629
  onProxyRes: (proxyRes, req) => {
608
630
  if (proxyRes.statusCode && proxyRes.statusCode >= 400) {
@@ -646,6 +668,9 @@ const RemoteServerFactory = exports.RemoteServerFactory = {
646
668
  // NOTE: Think about changing the name of this function to `applyApplicationExtensions`. First look into
647
669
  // what a common pattern is for application enhancement.
648
670
  (0, _express3.applyApplicationExtensions)(app);
671
+ if (options !== null && options !== void 0 && options.encodeNonAsciiHttpHeaders) {
672
+ app.use(encodeNonAsciiMiddleware);
673
+ }
649
674
  applyPatches(options);
650
675
  },
651
676
  /**
@@ -804,13 +829,29 @@ const RemoteServerFactory = exports.RemoteServerFactory = {
804
829
  * @param app {Express} - an Express App
805
830
  * @private
806
831
  */
807
- _createHandler(app) {
832
+ _createHandler(app, options) {
808
833
  // This flag is initially false, and is set true on the first request
809
834
  // handled by a Lambda. If it is true on entry to the handler function,
810
835
  // it indicates that the Lambda container has been reused.
811
836
  let lambdaContainerReused = false;
812
837
  const server = _awsServerlessExpress.default.createServer(app, null, binaryMimeTypes);
813
838
  const handler = (event, context, callback) => {
839
+ // encode non ASCII request headers
840
+ if (options !== null && options !== void 0 && options.encodeNonAsciiHttpHeaders) {
841
+ Object.keys(event.headers).forEach(key => {
842
+ if (!isASCII(event.headers[key])) {
843
+ event.headers[key] = encodeURIComponent(event.headers[key]);
844
+ // x-encoded-headers keeps track of which headers have been modified and encoded
845
+ if (event.headers[_constants.X_ENCODED_HEADERS]) {
846
+ // append header key
847
+ event.headers[_constants.X_ENCODED_HEADERS] = `${event.headers[_constants.X_ENCODED_HEADERS]},${key}`;
848
+ } else {
849
+ event.headers[_constants.X_ENCODED_HEADERS] = key;
850
+ }
851
+ }
852
+ });
853
+ }
854
+
814
855
  // We don't want to wait for an empty event loop once the response
815
856
  // has been sent. Setting this to false will "send the response
816
857
  // right away when the callback executes", but any pending events
@@ -912,8 +953,8 @@ const RemoteServerFactory = exports.RemoteServerFactory = {
912
953
  createHandler(options, customizeApp) {
913
954
  process.on('unhandledRejection', _ssrServer.catchAndLog);
914
955
  const app = this._createApp(options);
915
- customizeApp(app);
916
- return this._createHandler(app);
956
+ customizeApp(app, options);
957
+ return this._createHandler(app, options);
917
958
  },
918
959
  /**
919
960
  * @private
@@ -996,6 +1037,37 @@ const errorHandlerMiddleware = (err, req, res, next) => {
996
1037
  res.sendStatus(500);
997
1038
  };
998
1039
 
1040
+ /**
1041
+ * Helper function that checks if a string is composed of ASCII characters
1042
+ * We only check printable ASCII characters and not special ASCII characters
1043
+ * such as NULL
1044
+ *
1045
+ * @private
1046
+ */
1047
+ const isASCII = str => {
1048
+ return /^[\x20-\x7E]*$/.test(str);
1049
+ };
1050
+
1051
+ /**
1052
+ * Express Middleware applied to responses that encode any non ASCII headers
1053
+ *
1054
+ * @private
1055
+ */
1056
+ const encodeNonAsciiMiddleware = (req, res, next) => {
1057
+ const originalSetHeader = res.setHeader;
1058
+ res.setHeader = function (key, value) {
1059
+ if (!isASCII(value)) {
1060
+ originalSetHeader.call(this, key, encodeURIComponent(value));
1061
+ let encodedHeaders = res.getHeader(_constants.X_ENCODED_HEADERS);
1062
+ encodedHeaders = encodedHeaders ? `${encodedHeaders},${key}` : key;
1063
+ originalSetHeader.call(this, _constants.X_ENCODED_HEADERS, encodedHeaders);
1064
+ } else {
1065
+ originalSetHeader.call(this, key, value);
1066
+ }
1067
+ };
1068
+ next();
1069
+ };
1070
+
999
1071
  /**
1000
1072
  * Wrap the function fn in such a way that it will be called at most once. Subsequent
1001
1073
  * calls will always return the same value.
@@ -2,6 +2,8 @@
2
2
 
3
3
  var _supertest = _interopRequireDefault(require("supertest"));
4
4
  var _buildRemoteServer = require("./build-remote-server");
5
+ var _constants = require("./constants");
6
+ var _awsServerlessExpress = _interopRequireDefault(require("aws-serverless-express"));
5
7
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
6
8
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
7
9
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -13,6 +15,12 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
13
15
  * SPDX-License-Identifier: BSD-3-Clause
14
16
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
15
17
  */
18
+ jest.mock('aws-serverless-express', () => {
19
+ return {
20
+ createServer: jest.fn(),
21
+ proxy: jest.fn()
22
+ };
23
+ });
16
24
  const opts = (overrides = {}) => {
17
25
  const defaults = {
18
26
  buildDir: './src/ssr/server/test_fixtures',
@@ -178,4 +186,70 @@ describe('remote server factory test coverage', () => {
178
186
  // ]
179
187
  // ]).toF
180
188
  // })
181
- // })
189
+ // })
190
+ describe('encodeNonAsciiHttpHeaders flag in options to createHandler', () => {
191
+ test('encodes request headers', () => {
192
+ const mockApp = {
193
+ sendMetric: jest.fn()
194
+ };
195
+ const mockOptions = {
196
+ encodeNonAsciiHttpHeaders: true
197
+ };
198
+ const originalHeaders = {
199
+ 'x-non-ascii-header-one': 'テスト',
200
+ 'x-non-ascii-header-two': '测试',
201
+ 'x-regular-header': 'ascii-str'
202
+ };
203
+ const event = {
204
+ headers: _objectSpread({}, originalHeaders)
205
+ };
206
+ const expectedHeaders = {
207
+ 'x-non-ascii-header-one': '%E3%83%86%E3%82%B9%E3%83%88',
208
+ 'x-non-ascii-header-two': '%E6%B5%8B%E8%AF%95',
209
+ 'x-encoded-headers': 'x-non-ascii-header-one,x-non-ascii-header-two',
210
+ 'x-regular-header': 'ascii-str'
211
+ };
212
+ const {
213
+ handler
214
+ } = _buildRemoteServer.RemoteServerFactory._createHandler(mockApp, mockOptions);
215
+ expect(event.headers).toEqual(originalHeaders);
216
+ handler(event, {}, {});
217
+ expect(event.headers).toEqual(expectedHeaders);
218
+ expect(decodeURIComponent(event.headers['x-non-ascii-header-one'])).toEqual(originalHeaders['x-non-ascii-header-one']);
219
+ });
220
+ test('encodes response headers', () => {
221
+ const mockApp = {
222
+ use: jest.fn()
223
+ };
224
+ const mockOptions = {
225
+ encodeNonAsciiHttpHeaders: true
226
+ };
227
+ const res = {
228
+ headers: {},
229
+ setHeader: (key, value) => {
230
+ res.headers[key] = value;
231
+ },
232
+ getHeader: key => {
233
+ return res.headers[key];
234
+ }
235
+ };
236
+ const nonASCIIheader = 'x-non-ascii-header';
237
+ const nonASCIIstr = 'テスト';
238
+ const expectedEncoding = '%E3%83%86%E3%82%B9%E3%83%88';
239
+ const regularHeaderKey = 'x-regular-header';
240
+ const regularHeaderValue = 'ascii-str';
241
+ _buildRemoteServer.RemoteServerFactory._setupCommonMiddleware(mockApp, mockOptions);
242
+ const encodeNonAsciiMiddleware = mockApp.use.mock.calls[3][0];
243
+ res.setHeader(nonASCIIheader, nonASCIIstr);
244
+ expect(res.getHeader(nonASCIIheader)).toEqual(nonASCIIstr);
245
+ encodeNonAsciiMiddleware({}, res, () => {});
246
+ res.setHeader(nonASCIIheader, nonASCIIstr);
247
+ expect(res.getHeader(nonASCIIheader)).toEqual(expectedEncoding);
248
+ expect(decodeURI(expectedEncoding)).toEqual(nonASCIIstr);
249
+ expect(res.getHeader(_constants.X_ENCODED_HEADERS)).toEqual(nonASCIIheader);
250
+
251
+ // confirm ASCII headers are not modified
252
+ res.setHeader(regularHeaderKey, regularHeaderValue);
253
+ expect(res.getHeader(regularHeaderKey)).toEqual(regularHeaderValue);
254
+ });
255
+ });
@@ -8,6 +8,7 @@ export const CONTENT_ENCODING: "content-encoding";
8
8
  export const X_ORIGINAL_CONTENT_TYPE: "x-original-content-type";
9
9
  export const X_MOBIFY_QUERYSTRING: "x-mobify-querystring";
10
10
  export const X_MOBIFY_FROM_CACHE: "x-mobify-from-cache";
11
+ export const X_ENCODED_HEADERS: "x-encoded-headers";
11
12
  export const SET_COOKIE: "set-cookie";
12
13
  export const CACHE_CONTROL: "cache-control";
13
14
  export const NO_CACHE: "max-age=0, nocache, nostore, must-revalidate";
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/ssr/server/constants.js"],"names":[],"mappings":"AAMA,kEAAkE;AAClE,4BAA4B;AAC5B,4CAA4C;AAE5C,oEAAoE;AACpE,gDAAgD;AAGhD,0CAA0C;AAC1C,kDAAkD;AAClD,gEAAgE;AAChE,0DAA0D;AAC1D,wDAAwD;AACxD,sCAAsC;AACtC,4CAA4C;AAC5C,sEAAsE;AACtE,gEAAgE;AAChE,oEAAoE;AAEpE,2EAA2E;AAC3E,4DAA4D"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/ssr/server/constants.js"],"names":[],"mappings":"AAMA,kEAAkE;AAClE,4BAA4B;AAC5B,4CAA4C;AAE5C,oEAAoE;AACpE,gDAAgD;AAGhD,0CAA0C;AAC1C,kDAAkD;AAClD,gEAAgE;AAChE,0DAA0D;AAC1D,wDAAwD;AACxD,oDAAoD;AACpD,sCAAsC;AACtC,4CAA4C;AAC5C,sEAAsE;AACtE,gEAAgE;AAChE,oEAAoE;AAEpE,2EAA2E;AAC3E,4DAA4D"}
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.X_ORIGINAL_CONTENT_TYPE = exports.X_MOBIFY_QUERYSTRING = exports.X_MOBIFY_FROM_CACHE = exports.STRICT_TRANSPORT_SECURITY = exports.STATIC_ASSETS = exports.SLAS_CUSTOM_PROXY_PATH = exports.SET_COOKIE = exports.PROXY_PATH_PREFIX = exports.NO_CACHE = exports.CONTENT_TYPE = exports.CONTENT_SECURITY_POLICY = exports.CONTENT_ENCODING = exports.CACHE_CONTROL = exports.BUILD = exports.APPLICATION_OCTET_STREAM = void 0;
6
+ exports.X_ORIGINAL_CONTENT_TYPE = exports.X_MOBIFY_QUERYSTRING = exports.X_MOBIFY_FROM_CACHE = exports.X_ENCODED_HEADERS = exports.STRICT_TRANSPORT_SECURITY = exports.STATIC_ASSETS = exports.SLAS_CUSTOM_PROXY_PATH = exports.SET_COOKIE = exports.PROXY_PATH_PREFIX = exports.NO_CACHE = exports.CONTENT_TYPE = exports.CONTENT_SECURITY_POLICY = exports.CONTENT_ENCODING = exports.CACHE_CONTROL = exports.BUILD = exports.APPLICATION_OCTET_STREAM = void 0;
7
7
  /*
8
8
  * Copyright (c) 2021, salesforce.com, inc.
9
9
  * All rights reserved.
@@ -23,6 +23,7 @@ const CONTENT_ENCODING = exports.CONTENT_ENCODING = 'content-encoding';
23
23
  const X_ORIGINAL_CONTENT_TYPE = exports.X_ORIGINAL_CONTENT_TYPE = 'x-original-content-type';
24
24
  const X_MOBIFY_QUERYSTRING = exports.X_MOBIFY_QUERYSTRING = 'x-mobify-querystring';
25
25
  const X_MOBIFY_FROM_CACHE = exports.X_MOBIFY_FROM_CACHE = 'x-mobify-from-cache';
26
+ const X_ENCODED_HEADERS = exports.X_ENCODED_HEADERS = 'x-encoded-headers';
26
27
  const SET_COOKIE = exports.SET_COOKIE = 'set-cookie';
27
28
  const CACHE_CONTROL = exports.CACHE_CONTROL = 'cache-control';
28
29
  const NO_CACHE = exports.NO_CACHE = 'max-age=0, nocache, nostore, must-revalidate';
@@ -19,6 +19,8 @@ var _crypto = require("crypto");
19
19
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
20
20
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
21
21
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
22
+ function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
23
+ function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
22
24
  function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
23
25
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
24
26
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -477,6 +479,40 @@ describe('SSRServer operation', () => {
477
479
  expect(response.headers['set-cookie']).toBeUndefined();
478
480
  });
479
481
  });
482
+ test('should set xForwardedOrigin based on defined x-forwarded-host and x-forwarded-proto headers', () => {
483
+ process.env = {
484
+ MRT_ALLOW_COOKIES: 'true'
485
+ };
486
+ const forwardedHost = 'www.example.com';
487
+ const forwardedProto = 'https';
488
+ const app = _buildRemoteServer.RemoteServerFactory._createApp(opts());
489
+ const route = (req, res) => {
490
+ expect(req.headers['x-forwarded-host']).toBe(forwardedHost);
491
+ expect(res.locals.xForwardedOrigin).toBe(`${forwardedProto}://${forwardedHost}`);
492
+ res.sendStatus(200);
493
+ };
494
+ app.get('/*', route);
495
+ return (0, _supertest.default)(app).get('/').set('x-forwarded-host', forwardedHost).set('x-forwarded-proto', 'https').then(response => {
496
+ expect(response.status).toBe(200);
497
+ });
498
+ });
499
+ test('should set xForwardedOrigin based on defined x-forwarded-host and undefined x-forwarded-proto headers', () => {
500
+ process.env = {
501
+ MRT_ALLOW_COOKIES: 'true'
502
+ };
503
+ const options = opts();
504
+ const forwardedHost = 'www.example.com';
505
+ const app = _buildRemoteServer.RemoteServerFactory._createApp(options);
506
+ const route = (req, res) => {
507
+ expect(req.headers['x-forwarded-host']).toBe(forwardedHost);
508
+ expect(res.locals.xForwardedOrigin).toBe(`${options.protocol}://${forwardedHost}`);
509
+ res.sendStatus(200);
510
+ };
511
+ app.get('/*', route);
512
+ return (0, _supertest.default)(app).get('/').set('x-forwarded-host', forwardedHost).then(response => {
513
+ expect(response.status).toBe(200);
514
+ });
515
+ });
480
516
  test(`should reject POST requests to /`, () => {
481
517
  const app = _buildRemoteServer.RemoteServerFactory._createApp(opts());
482
518
  const route = (req, res) => {
@@ -948,5 +984,50 @@ describe('SLAS private client proxy', () => {
948
984
  expect(response.body.host).toBe('shortCode.api.commercecloud.salesforce.com');
949
985
  expect(response.body['x-mobify']).toBe('true');
950
986
  });
951
- });
987
+ }, 15000);
988
+ test('does not add _sfdc_client_auth header if request not for /oauth2/trusted-agent/token', /*#__PURE__*/_asyncToGenerator(function* () {
989
+ process.env.PWA_KIT_SLAS_CLIENT_SECRET = 'a secret';
990
+ const encodedCredentials = Buffer.from('clientId:a secret').toString('base64');
991
+ const app = _buildRemoteServer.RemoteServerFactory._createApp(opts({
992
+ mobify: {
993
+ app: {
994
+ commerceAPI: {
995
+ parameters: {
996
+ clientId: 'clientId',
997
+ shortCode: 'shortCode'
998
+ }
999
+ }
1000
+ }
1001
+ },
1002
+ useSLASPrivateClient: true,
1003
+ slasTarget: slasTarget
1004
+ }));
1005
+ return yield (0, _supertest.default)(app).get('/mobify/slas/oauth2/other-path').then(response => {
1006
+ expect(response.body._sfdc_client_auth).toBeUndefined();
1007
+ });
1008
+ }), 15000);
1009
+ test('adds _sfdc_client_auth header if request is for /oauth2/trusted-agent/token', /*#__PURE__*/_asyncToGenerator(function* () {
1010
+ process.env.PWA_KIT_SLAS_CLIENT_SECRET = 'a secret';
1011
+ const encodedCredentials = Buffer.from('clientId:a secret').toString('base64');
1012
+ const app = _buildRemoteServer.RemoteServerFactory._createApp(opts({
1013
+ mobify: {
1014
+ app: {
1015
+ commerceAPI: {
1016
+ parameters: {
1017
+ clientId: 'clientId',
1018
+ shortCode: 'shortCode'
1019
+ }
1020
+ }
1021
+ }
1022
+ },
1023
+ useSLASPrivateClient: true,
1024
+ slasTarget: slasTarget,
1025
+ trustedAgentAuthPathMatch: /\/oauth2\/trusted-agent\/token/
1026
+ }));
1027
+ return yield (0, _supertest.default)(app).get('/mobify/slas/private/oauth2/trusted-agent/token').then(response => {
1028
+ expect(response.body['_sfdc_client_auth']).toBe(encodedCredentials);
1029
+ expect(response.body.host).toBe('shortCode.api.commercecloud.salesforce.com');
1030
+ expect(response.body['x-mobify']).toBe('true');
1031
+ });
1032
+ }), 15000);
952
1033
  });