@sap-ux/backend-proxy-middleware 0.10.1 → 0.10.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/dist/base/proxy.d.ts +18 -10
- package/dist/base/proxy.js +65 -40
- package/dist/ext/bsp.d.ts +0 -7
- package/dist/ext/bsp.js +0 -19
- package/package.json +3 -3
package/dist/base/proxy.d.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import type { ServerOptions } from 'http-proxy';
|
|
2
|
-
import type { RequestHandler, Options } from 'http-proxy-middleware';
|
|
3
|
-
import type { ClientRequest, IncomingMessage, ServerResponse } from 'http';
|
|
4
1
|
import { ToolsLogger, type Logger } from '@sap-ux/logger';
|
|
2
|
+
import type { ClientRequest, IncomingMessage, ServerResponse } from 'http';
|
|
3
|
+
import type { ServerOptions } from 'http-proxy';
|
|
4
|
+
import type { Options, RequestHandler } from 'http-proxy-middleware';
|
|
5
5
|
import type { BackendConfig, DestinationBackendConfig } from './types';
|
|
6
6
|
import type { BackendSystem } from '@sap-ux/store';
|
|
7
|
-
import
|
|
8
|
-
import type { Socket } from 'node:net';
|
|
9
|
-
import type { Request } from 'express';
|
|
7
|
+
import { AuthenticationType } from '@sap-ux/store';
|
|
10
8
|
import type connect from 'connect';
|
|
9
|
+
import type { Request } from 'express';
|
|
10
|
+
import type { Socket } from 'node:net';
|
|
11
|
+
import type { Url } from 'node:url';
|
|
11
12
|
export type EnhancedIncomingMessage = (IncomingMessage & Pick<Request, 'originalUrl'>) | connect.IncomingMessage;
|
|
12
13
|
/**
|
|
13
14
|
* Collection of custom event handler for the proxy.
|
|
@@ -50,6 +51,13 @@ export declare function proxyErrorHandler(err: Error & {
|
|
|
50
51
|
* Collection of path rewrite functions.
|
|
51
52
|
*/
|
|
52
53
|
export declare const PathRewriters: {
|
|
54
|
+
/**
|
|
55
|
+
* Generates a rewrite function that replaces the matched string with '/manifest.json'.
|
|
56
|
+
*
|
|
57
|
+
* @param bspPath the bsp path from the yaml config
|
|
58
|
+
* @returns a path rewrite function
|
|
59
|
+
*/
|
|
60
|
+
convertAppDescriptorToManifest(bspPath: string): (path: string) => string;
|
|
53
61
|
/**
|
|
54
62
|
* Generates a rewrite function that replaces the matched string with the prefix in the given string.
|
|
55
63
|
*
|
|
@@ -59,7 +67,7 @@ export declare const PathRewriters: {
|
|
|
59
67
|
*/
|
|
60
68
|
replacePrefix(match: string, prefix: string): (path: string) => string;
|
|
61
69
|
/**
|
|
62
|
-
* Add or replace the sap-client url parameter if missing or
|
|
70
|
+
* Add or replace the sap-client url parameter if missing or incorrect in the original request path.
|
|
63
71
|
*
|
|
64
72
|
* @param client sap-client as string
|
|
65
73
|
* @returns a path rewrite function
|
|
@@ -82,7 +90,7 @@ export declare function initI18n(): Promise<void>;
|
|
|
82
90
|
* Enhance the proxy options and backend configurations for the usage of destinations in SAP Business Application Studio.
|
|
83
91
|
*
|
|
84
92
|
* @param proxyOptions reference to a proxy options object that the function will enhance
|
|
85
|
-
* @param backend reference to the backend configuration that the
|
|
93
|
+
* @param backend reference to the backend configuration that the function may enhance
|
|
86
94
|
*/
|
|
87
95
|
export declare function enhanceConfigsForDestination(proxyOptions: Options & {
|
|
88
96
|
headers: object;
|
|
@@ -92,12 +100,12 @@ export declare function enhanceConfigsForDestination(proxyOptions: Options & {
|
|
|
92
100
|
*
|
|
93
101
|
* @param proxyOptions reference to a proxy options object that the function will enhance
|
|
94
102
|
* @param system backend system information (most likely) read from the store
|
|
95
|
-
* @param
|
|
103
|
+
* @param authType determines the authentication protocol to be used
|
|
96
104
|
* @param tokenChangedCallback function to call if a new refreshToken is available
|
|
97
105
|
*/
|
|
98
106
|
export declare function enhanceConfigForSystem(proxyOptions: Options & {
|
|
99
107
|
headers: object;
|
|
100
|
-
}, system: BackendSystem | undefined,
|
|
108
|
+
}, system: BackendSystem | undefined, authType: AuthenticationType, tokenChangedCallback: (refreshToken?: string) => void): Promise<void>;
|
|
101
109
|
/**
|
|
102
110
|
* Generate options for the proxy middleware based on the input.
|
|
103
111
|
*
|
package/dist/base/proxy.js
CHANGED
|
@@ -10,17 +10,17 @@ exports.enhanceConfigsForDestination = enhanceConfigsForDestination;
|
|
|
10
10
|
exports.enhanceConfigForSystem = enhanceConfigForSystem;
|
|
11
11
|
exports.generateProxyMiddlewareOptions = generateProxyMiddlewareOptions;
|
|
12
12
|
exports.createProxy = createProxy;
|
|
13
|
-
const https_proxy_agent_1 = require("https-proxy-agent");
|
|
14
|
-
const http_proxy_middleware_1 = require("http-proxy-middleware");
|
|
15
|
-
const i18next_1 = __importDefault(require("i18next"));
|
|
16
|
-
const logger_1 = require("@sap-ux/logger");
|
|
17
13
|
const axios_extension_1 = require("@sap-ux/axios-extension");
|
|
18
14
|
const btp_utils_1 = require("@sap-ux/btp-utils");
|
|
15
|
+
const logger_1 = require("@sap-ux/logger");
|
|
16
|
+
const http_proxy_middleware_1 = require("http-proxy-middleware");
|
|
17
|
+
const https_proxy_agent_1 = require("https-proxy-agent");
|
|
18
|
+
const i18next_1 = __importDefault(require("i18next"));
|
|
19
19
|
const i18n_json_1 = __importDefault(require("./i18n.json"));
|
|
20
20
|
const store_1 = require("@sap-ux/store");
|
|
21
|
-
const config_1 = require("./config");
|
|
22
|
-
const bsp_1 = require("../ext/bsp");
|
|
23
21
|
const proxy_from_env_1 = require("proxy-from-env");
|
|
22
|
+
const bsp_1 = require("../ext/bsp");
|
|
23
|
+
const config_1 = require("./config");
|
|
24
24
|
/**
|
|
25
25
|
* Collection of custom event handler for the proxy.
|
|
26
26
|
*/
|
|
@@ -107,6 +107,16 @@ async function getApiHubKey(logger) {
|
|
|
107
107
|
* Collection of path rewrite functions.
|
|
108
108
|
*/
|
|
109
109
|
exports.PathRewriters = {
|
|
110
|
+
/**
|
|
111
|
+
* Generates a rewrite function that replaces the matched string with '/manifest.json'.
|
|
112
|
+
*
|
|
113
|
+
* @param bspPath the bsp path from the yaml config
|
|
114
|
+
* @returns a path rewrite function
|
|
115
|
+
*/
|
|
116
|
+
convertAppDescriptorToManifest(bspPath) {
|
|
117
|
+
const regex = new RegExp('(' + bspPath + '/manifest\\.appdescr\\b)');
|
|
118
|
+
return (path) => (path.match(regex) ? '/manifest.json' : path);
|
|
119
|
+
},
|
|
110
120
|
/**
|
|
111
121
|
* Generates a rewrite function that replaces the matched string with the prefix in the given string.
|
|
112
122
|
*
|
|
@@ -118,7 +128,7 @@ exports.PathRewriters = {
|
|
|
118
128
|
return (path) => path.replace(match, prefix.replace(/\/$/, ''));
|
|
119
129
|
},
|
|
120
130
|
/**
|
|
121
|
-
* Add or replace the sap-client url parameter if missing or
|
|
131
|
+
* Add or replace the sap-client url parameter if missing or incorrect in the original request path.
|
|
122
132
|
*
|
|
123
133
|
* @param client sap-client as string
|
|
124
134
|
* @returns a path rewrite function
|
|
@@ -154,6 +164,9 @@ exports.PathRewriters = {
|
|
|
154
164
|
if (config.client) {
|
|
155
165
|
functions.push(exports.PathRewriters.replaceClient(config.client));
|
|
156
166
|
}
|
|
167
|
+
if (config.bsp) {
|
|
168
|
+
functions.push(exports.PathRewriters.convertAppDescriptorToManifest(config.bsp));
|
|
169
|
+
}
|
|
157
170
|
if (functions.length > 0) {
|
|
158
171
|
return (path, req) => {
|
|
159
172
|
let newPath = path;
|
|
@@ -199,7 +212,7 @@ async function initI18n() {
|
|
|
199
212
|
* Enhance the proxy options and backend configurations for the usage of destinations in SAP Business Application Studio.
|
|
200
213
|
*
|
|
201
214
|
* @param proxyOptions reference to a proxy options object that the function will enhance
|
|
202
|
-
* @param backend reference to the backend configuration that the
|
|
215
|
+
* @param backend reference to the backend configuration that the function may enhance
|
|
203
216
|
*/
|
|
204
217
|
async function enhanceConfigsForDestination(proxyOptions, backend) {
|
|
205
218
|
proxyOptions.target = (0, btp_utils_1.getDestinationUrlForAppStudio)(backend.destination);
|
|
@@ -226,11 +239,11 @@ async function enhanceConfigsForDestination(proxyOptions, backend) {
|
|
|
226
239
|
*
|
|
227
240
|
* @param proxyOptions reference to a proxy options object that the function will enhance
|
|
228
241
|
* @param system backend system information (most likely) read from the store
|
|
229
|
-
* @param
|
|
242
|
+
* @param authType determines the authentication protocol to be used
|
|
230
243
|
* @param tokenChangedCallback function to call if a new refreshToken is available
|
|
231
244
|
*/
|
|
232
|
-
async function enhanceConfigForSystem(proxyOptions, system,
|
|
233
|
-
if (
|
|
245
|
+
async function enhanceConfigForSystem(proxyOptions, system, authType, tokenChangedCallback) {
|
|
246
|
+
if (authType === store_1.AuthenticationType.OAuth2RefreshToken) {
|
|
234
247
|
if (system?.serviceKeys) {
|
|
235
248
|
const provider = (0, axios_extension_1.createForAbapOnCloud)({
|
|
236
249
|
environment: axios_extension_1.AbapCloudEnvironment.Standalone,
|
|
@@ -242,10 +255,10 @@ async function enhanceConfigForSystem(proxyOptions, system, oAuthRequired, token
|
|
|
242
255
|
await provider.getAtoInfo();
|
|
243
256
|
}
|
|
244
257
|
else {
|
|
245
|
-
throw new Error('Cannot connect to ABAP Environment on BTP without service keys.');
|
|
258
|
+
throw new Error('Cannot connect to ABAP Environment on BTP using OAuth without service keys.');
|
|
246
259
|
}
|
|
247
260
|
}
|
|
248
|
-
else if (system
|
|
261
|
+
else if (system && authType === store_1.AuthenticationType.ReentranceTicket) {
|
|
249
262
|
const provider = (0, axios_extension_1.createForAbapOnCloud)({
|
|
250
263
|
ignoreCertErrors: proxyOptions.secure === false,
|
|
251
264
|
environment: axios_extension_1.AbapCloudEnvironment.EmbeddedSteampunk,
|
|
@@ -296,33 +309,7 @@ async function generateProxyMiddlewareOptions(backend, options = {}, logger = ne
|
|
|
296
309
|
}
|
|
297
310
|
}
|
|
298
311
|
else {
|
|
299
|
-
|
|
300
|
-
// check if system credentials are stored in the store
|
|
301
|
-
try {
|
|
302
|
-
const systemStore = await (0, store_1.getService)({ logger, entityName: 'system' });
|
|
303
|
-
const system = (await systemStore.read(new store_1.BackendSystemKey({ url: localBackend.url, client: localBackend.client }))) ?? {
|
|
304
|
-
name: '<unknown>',
|
|
305
|
-
url: localBackend.url,
|
|
306
|
-
authenticationType: localBackend.authenticationType
|
|
307
|
-
};
|
|
308
|
-
await enhanceConfigForSystem(proxyOptions, system, backend.scp, (refreshToken, accessToken) => {
|
|
309
|
-
if (refreshToken) {
|
|
310
|
-
logger.info('Updating refresh token for: ' + localBackend.url);
|
|
311
|
-
systemStore.write({ ...system, refreshToken }).catch((error) => logger.error(error));
|
|
312
|
-
}
|
|
313
|
-
if (accessToken) {
|
|
314
|
-
logger.info('Setting access token');
|
|
315
|
-
proxyOptions.headers['authorization'] = `bearer ${accessToken}`;
|
|
316
|
-
}
|
|
317
|
-
else {
|
|
318
|
-
logger.warn('Setting of access token failed.');
|
|
319
|
-
}
|
|
320
|
-
});
|
|
321
|
-
}
|
|
322
|
-
catch (error) {
|
|
323
|
-
logger.warn('Accessing the credentials store failed.');
|
|
324
|
-
logger.debug(error);
|
|
325
|
-
}
|
|
312
|
+
await updateProxyConfigFromStore(backend, logger, proxyOptions);
|
|
326
313
|
}
|
|
327
314
|
if (!proxyOptions.auth && process.env.FIORI_TOOLS_USER && process.env.FIORI_TOOLS_PASSWORD) {
|
|
328
315
|
proxyOptions.auth = `${process.env.FIORI_TOOLS_USER}:${process.env.FIORI_TOOLS_PASSWORD}`;
|
|
@@ -348,6 +335,44 @@ async function generateProxyMiddlewareOptions(backend, options = {}, logger = ne
|
|
|
348
335
|
logger.info(`Backend proxy created for ${proxyOptions.target}`);
|
|
349
336
|
return proxyOptions;
|
|
350
337
|
}
|
|
338
|
+
/**
|
|
339
|
+
* Determine the correct authentication configuration for connections from a non-BAS platform.
|
|
340
|
+
*
|
|
341
|
+
* @param backend the backend config loaded from the yaml config
|
|
342
|
+
* @param logger a logger instance
|
|
343
|
+
* @param proxyOptions additional proxy header, request and response settings
|
|
344
|
+
*/
|
|
345
|
+
async function updateProxyConfigFromStore(backend, logger, proxyOptions) {
|
|
346
|
+
const localBackend = backend;
|
|
347
|
+
// check if system credentials are stored in the store
|
|
348
|
+
try {
|
|
349
|
+
const systemStore = await (0, store_1.getService)({ logger, entityName: 'system' });
|
|
350
|
+
const system = (await systemStore.read(new store_1.BackendSystemKey({ url: localBackend.url, client: localBackend.client }))) ?? {
|
|
351
|
+
name: '<unknown>',
|
|
352
|
+
url: localBackend.url,
|
|
353
|
+
authenticationType: localBackend.authenticationType
|
|
354
|
+
};
|
|
355
|
+
// Auth type is determined from app config as we may have multiple stored systems with the same url/client using different auth types
|
|
356
|
+
await enhanceConfigForSystem(proxyOptions, system, localBackend.authenticationType ??
|
|
357
|
+
(localBackend.scp ? store_1.AuthenticationType.OAuth2RefreshToken : store_1.AuthenticationType.Basic), (refreshToken, accessToken) => {
|
|
358
|
+
if (refreshToken) {
|
|
359
|
+
logger.info('Updating refresh token for: ' + localBackend.url);
|
|
360
|
+
systemStore.write({ ...system, refreshToken }).catch((error) => logger.error(error));
|
|
361
|
+
}
|
|
362
|
+
if (accessToken) {
|
|
363
|
+
logger.info('Setting access token');
|
|
364
|
+
proxyOptions.headers['authorization'] = `bearer ${accessToken}`;
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
367
|
+
logger.warn('Setting of access token failed.');
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
catch (error) {
|
|
372
|
+
logger.warn('Accessing the credentials store failed.');
|
|
373
|
+
logger.debug(error);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
351
376
|
/**
|
|
352
377
|
* Generate an instance of the proxy middleware based on the input.
|
|
353
378
|
*
|
package/dist/ext/bsp.d.ts
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
import type { Options } from 'http-proxy-middleware';
|
|
2
2
|
import type { Logger } from '@sap-ux/logger';
|
|
3
|
-
/**
|
|
4
|
-
* Replace calls to manifest.appdescr file if we are running the FLP embedded flow.
|
|
5
|
-
*
|
|
6
|
-
* @param bsp path of the BSP page
|
|
7
|
-
* @returns a path rewrite function
|
|
8
|
-
*/
|
|
9
|
-
export declare function convertAppDescriptorToManifest(bsp: string): (path: string) => string;
|
|
10
3
|
/**
|
|
11
4
|
* Prompts the user for credentials.
|
|
12
5
|
*
|
package/dist/ext/bsp.js
CHANGED
|
@@ -3,23 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.convertAppDescriptorToManifest = convertAppDescriptorToManifest;
|
|
7
6
|
exports.promptUserPass = promptUserPass;
|
|
8
7
|
exports.addOptionsForEmbeddedBSP = addOptionsForEmbeddedBSP;
|
|
9
8
|
const chalk_1 = require("chalk");
|
|
10
9
|
const i18next_1 = __importDefault(require("i18next"));
|
|
11
10
|
const prompts_1 = __importDefault(require("prompts"));
|
|
12
11
|
const btp_utils_1 = require("@sap-ux/btp-utils");
|
|
13
|
-
/**
|
|
14
|
-
* Replace calls to manifest.appdescr file if we are running the FLP embedded flow.
|
|
15
|
-
*
|
|
16
|
-
* @param bsp path of the BSP page
|
|
17
|
-
* @returns a path rewrite function
|
|
18
|
-
*/
|
|
19
|
-
function convertAppDescriptorToManifest(bsp) {
|
|
20
|
-
const regex = new RegExp('(' + bsp + '/manifest\\.appdescr\\b)');
|
|
21
|
-
return (path) => (path.match(regex) ? '/manifest.json' : path);
|
|
22
|
-
}
|
|
23
12
|
/**
|
|
24
13
|
* Prompts the user for credentials.
|
|
25
14
|
*
|
|
@@ -98,14 +87,6 @@ async function addOptionsForEmbeddedBSP(bspPath, proxyOptions, logger) {
|
|
|
98
87
|
return undefined;
|
|
99
88
|
}
|
|
100
89
|
};
|
|
101
|
-
if (proxyOptions.pathRewrite) {
|
|
102
|
-
const oldRewrite = proxyOptions.pathRewrite;
|
|
103
|
-
const appDescrRewrite = convertAppDescriptorToManifest(bspPath);
|
|
104
|
-
proxyOptions.pathRewrite = (path) => appDescrRewrite(oldRewrite(path));
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
proxyOptions.pathRewrite = convertAppDescriptorToManifest(bspPath);
|
|
108
|
-
}
|
|
109
90
|
if (!proxyOptions.auth) {
|
|
110
91
|
proxyOptions.auth = await promptUserPass(logger);
|
|
111
92
|
}
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"bugs": {
|
|
10
10
|
"url": "https://github.com/SAP/open-ux-tools/issues?q=is%3Aopen+is%3Aissue+label%3Abug+label%3Abackend-proxy-middleware"
|
|
11
11
|
},
|
|
12
|
-
"version": "0.10.
|
|
12
|
+
"version": "0.10.3",
|
|
13
13
|
"license": "Apache-2.0",
|
|
14
14
|
"author": "@SAP/ux-tools-team",
|
|
15
15
|
"main": "dist/index.js",
|
|
@@ -28,10 +28,10 @@
|
|
|
28
28
|
"i18next": "25.3.0",
|
|
29
29
|
"prompts": "2.4.2",
|
|
30
30
|
"proxy-from-env": "1.1.0",
|
|
31
|
-
"@sap-ux/axios-extension": "1.
|
|
31
|
+
"@sap-ux/axios-extension": "1.23.0",
|
|
32
32
|
"@sap-ux/btp-utils": "1.1.4",
|
|
33
33
|
"@sap-ux/logger": "0.7.0",
|
|
34
|
-
"@sap-ux/store": "1.
|
|
34
|
+
"@sap-ux/store": "1.2.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/express": "4.17.21",
|