@salesforce/pwa-kit-runtime 4.0.0-extensibility-preview.2 → 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 +6 -6
- package/ssr/server/build-remote-server.d.ts +6 -1
- package/ssr/server/build-remote-server.d.ts.map +1 -1
- package/ssr/server/build-remote-server.js +76 -4
- package/ssr/server/build-remote-server.test.js +75 -1
- package/ssr/server/constants.d.ts +1 -0
- package/ssr/server/constants.d.ts.map +1 -1
- package/ssr/server/constants.js +2 -1
- package/ssr/server/express.test.js +82 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/pwa-kit-runtime",
|
|
3
|
-
"version": "4.0.0-extensibility-preview.
|
|
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.
|
|
50
|
-
"@salesforce/pwa-kit-extension-sdk": "4.0.0-extensibility-preview.
|
|
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.
|
|
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.
|
|
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": "
|
|
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":"
|
|
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"}
|
package/ssr/server/constants.js
CHANGED
|
@@ -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
|
});
|