Socket
Socket
Sign inDemoInstall

@sap-ux/backend-proxy-middleware

Package Overview
Dependencies
Maintainers
0
Versions
133
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sap-ux/backend-proxy-middleware - npm Package Compare versions

Comparing version 0.7.41 to 0.8.1

309

dist/base/proxy.js
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {

@@ -40,4 +31,3 @@ return (mod && mod.__esModule) ? mod : { "default": mod };

onProxyReq(proxyReq, _req, _res, _options) {
var _a;
if (((_a = proxyReq.path) === null || _a === void 0 ? void 0 : _a.includes('Fiorilaunchpad.html')) && !proxyReq.headersSent) {
if (proxyReq.path?.includes('Fiorilaunchpad.html') && !proxyReq.headersSent) {
proxyReq.setHeader('accept-encoding', '*');

@@ -54,5 +44,4 @@ }

onProxyRes(proxyRes, _req, _res) {
var _a;
const header = (_a = proxyRes === null || proxyRes === void 0 ? void 0 : proxyRes.headers) === null || _a === void 0 ? void 0 : _a['set-cookie'];
if (header === null || header === void 0 ? void 0 : header.length) {
const header = proxyRes?.headers?.['set-cookie'];
if (header?.length) {
for (let i = header.length - 1; i >= 0; i--) {

@@ -75,4 +64,3 @@ const cookie = header[i].replace(/\s?Domain=[^\s]*\s?|\s?SameSite=[^\s]*\s?|\s?Secure[^\s]*\s?|\s?Partitioned[^\s]*\s?/gi, '');

function proxyErrorHandler(err, req, logger, _res, _target) {
var _a;
if (err && ((_a = err.stack) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== 'error') {
if (err && err.stack?.toLowerCase() !== 'error') {
let error;

@@ -104,15 +92,13 @@ if (err.code === 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY') {

*/
function getApiHubKey(logger) {
return __awaiter(this, void 0, void 0, function* () {
let apiHubKey = process.env.API_HUB_API_KEY;
if (!apiHubKey && !(0, btp_utils_1.isAppStudio)()) {
const apiHubStore = (yield (0, store_1.getService)({
logger,
entityName: 'api-hub'
}));
const apiHubSettings = yield apiHubStore.read();
apiHubKey = apiHubSettings ? apiHubSettings.apiKey : undefined;
}
return apiHubKey;
});
async function getApiHubKey(logger) {
let apiHubKey = process.env.API_HUB_API_KEY;
if (!apiHubKey && !(0, btp_utils_1.isAppStudio)()) {
const apiHubStore = (await (0, store_1.getService)({
logger,
entityName: 'api-hub'
}));
const apiHubSettings = await apiHubStore.read();
apiHubKey = apiHubSettings ? apiHubSettings.apiKey : undefined;
}
return apiHubKey;
}

@@ -190,16 +176,14 @@ /**

*/
function initI18n() {
return __awaiter(this, void 0, void 0, function* () {
const ns = 'backend-proxy-middleware';
yield i18next_1.default.init({
resources: {
en: {
[ns]: i18n_json_1.default
}
},
lng: 'en',
fallbackLng: 'en',
defaultNS: ns,
ns: [ns]
});
async function initI18n() {
const ns = 'backend-proxy-middleware';
await i18next_1.default.init({
resources: {
en: {
[ns]: i18n_json_1.default
}
},
lng: 'en',
fallbackLng: 'en',
defaultNS: ns,
ns: [ns]
});

@@ -214,24 +198,21 @@ }

*/
function enhanceConfigsForDestination(proxyOptions, backend) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
proxyOptions.target = (0, btp_utils_1.getDestinationUrlForAppStudio)(backend.destination);
if (backend.destinationInstance) {
proxyOptions.headers[btp_utils_1.BAS_DEST_INSTANCE_CRED_HEADER] = yield (0, btp_utils_1.getCredentialsForDestinationService)(backend.destinationInstance);
async function enhanceConfigsForDestination(proxyOptions, backend) {
proxyOptions.target = (0, btp_utils_1.getDestinationUrlForAppStudio)(backend.destination);
if (backend.destinationInstance) {
proxyOptions.headers[btp_utils_1.BAS_DEST_INSTANCE_CRED_HEADER] = await (0, btp_utils_1.getCredentialsForDestinationService)(backend.destinationInstance);
}
else {
const destinations = await (0, btp_utils_1.listDestinations)();
const destination = destinations[backend.destination];
if (destination) {
// in case of a full url destination remove the path defined in the destination from the forwarded call
if ((0, btp_utils_1.isFullUrlDestination)(destination)) {
backend.path = new URL(destination.Host).pathname.replace(/\/$/, '');
backend.pathReplace = backend.pathReplace ?? '/';
}
}
else {
const destinations = yield (0, btp_utils_1.listDestinations)();
const destination = destinations[backend.destination];
if (destination) {
// in case of a full url destination remove the path defined in the destination from the forwarded call
if ((0, btp_utils_1.isFullUrlDestination)(destination)) {
backend.path = new URL(destination.Host).pathname.replace(/\/$/, '');
backend.pathReplace = (_a = backend.pathReplace) !== null && _a !== void 0 ? _a : '/';
}
}
else {
throw new Error();
}
throw new Error();
}
});
}
}

@@ -247,35 +228,33 @@ exports.enhanceConfigsForDestination = enhanceConfigsForDestination;

*/
function enhanceConfigForSystem(proxyOptions, system, oAuthRequired, tokenChangedCallback) {
return __awaiter(this, void 0, void 0, function* () {
if (oAuthRequired) {
if (system === null || system === void 0 ? void 0 : system.serviceKeys) {
const provider = (0, axios_extension_1.createForAbapOnCloud)({
environment: axios_extension_1.AbapCloudEnvironment.Standalone,
service: system.serviceKeys,
refreshToken: system.refreshToken,
refreshTokenChangedCb: tokenChangedCallback
});
// sending a request to the backend to get token
yield provider.getAtoInfo();
}
else {
throw new Error('Cannot connect to ABAP Environment on BTP without service keys.');
}
}
else if ((system === null || system === void 0 ? void 0 : system.authenticationType) === store_1.AuthenticationType.ReentranceTicket) {
async function enhanceConfigForSystem(proxyOptions, system, oAuthRequired, tokenChangedCallback) {
if (oAuthRequired) {
if (system?.serviceKeys) {
const provider = (0, axios_extension_1.createForAbapOnCloud)({
ignoreCertErrors: proxyOptions.secure === false,
environment: axios_extension_1.AbapCloudEnvironment.EmbeddedSteampunk,
url: system.url
environment: axios_extension_1.AbapCloudEnvironment.Standalone,
service: system.serviceKeys,
refreshToken: system.refreshToken,
refreshTokenChangedCb: tokenChangedCallback
});
// sending a request to the backend to get cookies
const ato = yield provider.getAtoInfo();
if (ato) {
proxyOptions.headers['cookie'] = provider.cookies.toString();
}
// sending a request to the backend to get token
await provider.getAtoInfo();
}
else if ((system === null || system === void 0 ? void 0 : system.username) && system.password) {
proxyOptions.auth = `${system.username}:${system.password}`;
else {
throw new Error('Cannot connect to ABAP Environment on BTP without service keys.');
}
});
}
else if (system?.authenticationType === store_1.AuthenticationType.ReentranceTicket) {
const provider = (0, axios_extension_1.createForAbapOnCloud)({
ignoreCertErrors: proxyOptions.secure === false,
environment: axios_extension_1.AbapCloudEnvironment.EmbeddedSteampunk,
url: system.url
});
// sending a request to the backend to get cookies
const ato = await provider.getAtoInfo();
if (ato) {
proxyOptions.headers['cookie'] = provider.cookies.toString();
}
}
else if (system?.username && system.password) {
proxyOptions.auth = `${system.username}:${system.password}`;
}
}

@@ -291,76 +270,78 @@ exports.enhanceConfigForSystem = enhanceConfigForSystem;

*/
function generateProxyMiddlewareOptions(backend, options = {}, logger = new logger_1.ToolsLogger()) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
// add required options
const proxyOptions = Object.assign(Object.assign(Object.assign({ headers: {} }, exports.ProxyEventHandlers), { onError: (err, req, res, target) => {
proxyErrorHandler(err, req, logger, res, target);
} }), options);
proxyOptions.changeOrigin = true;
proxyOptions.logProvider = () => logger;
// always set the target to the url provided in yaml
proxyOptions.target = backend.url;
// overwrite url if running in AppStudio
if ((0, btp_utils_1.isAppStudio)()) {
const destBackend = backend;
destBackend.destination = (_a = destBackend.destination) !== null && _a !== void 0 ? _a : process.env.FIORI_TOOLS_DESTINATION;
if (destBackend.destination) {
yield enhanceConfigsForDestination(proxyOptions, destBackend);
logger.info('Using destination: ' + destBackend.destination);
}
async function generateProxyMiddlewareOptions(backend, options = {}, logger = new logger_1.ToolsLogger()) {
// add required options
const proxyOptions = {
headers: {},
...exports.ProxyEventHandlers,
onError: (err, req, res, target) => {
proxyErrorHandler(err, req, logger, res, target);
},
...options
};
proxyOptions.changeOrigin = true;
proxyOptions.logProvider = () => logger;
// always set the target to the url provided in yaml
proxyOptions.target = backend.url;
// overwrite url if running in AppStudio
if ((0, btp_utils_1.isAppStudio)()) {
const destBackend = backend;
destBackend.destination = destBackend.destination ?? process.env.FIORI_TOOLS_DESTINATION;
if (destBackend.destination) {
await enhanceConfigsForDestination(proxyOptions, destBackend);
logger.info('Using destination: ' + destBackend.destination);
}
else {
const localBackend = backend;
// check if system credentials are stored in the store
try {
const systemStore = yield (0, store_1.getService)({ logger, entityName: 'system' });
const system = (_b = (yield systemStore.read(new store_1.BackendSystemKey({ url: localBackend.url, client: localBackend.client })))) !== null && _b !== void 0 ? _b : {
name: '<unknown>',
url: localBackend.url,
authenticationType: localBackend.authenticationType
};
yield enhanceConfigForSystem(proxyOptions, system, backend.scp, (refreshToken, accessToken) => {
if (refreshToken) {
logger.info('Updating refresh token for: ' + localBackend.url);
systemStore.write(Object.assign(Object.assign({}, system), { refreshToken })).catch((error) => logger.error(error));
}
if (accessToken) {
logger.info('Setting access token');
proxyOptions.headers['authorization'] = `bearer ${accessToken}`;
}
else {
logger.warn('Setting of access token failed.');
}
});
}
catch (error) {
logger.warn('Accessing the credentials store failed.');
logger.debug(error);
}
}
else {
const localBackend = backend;
// check if system credentials are stored in the store
try {
const systemStore = await (0, store_1.getService)({ logger, entityName: 'system' });
const system = (await systemStore.read(new store_1.BackendSystemKey({ url: localBackend.url, client: localBackend.client }))) ?? {
name: '<unknown>',
url: localBackend.url,
authenticationType: localBackend.authenticationType
};
await enhanceConfigForSystem(proxyOptions, system, backend.scp, (refreshToken, accessToken) => {
if (refreshToken) {
logger.info('Updating refresh token for: ' + localBackend.url);
systemStore.write({ ...system, refreshToken }).catch((error) => logger.error(error));
}
if (accessToken) {
logger.info('Setting access token');
proxyOptions.headers['authorization'] = `bearer ${accessToken}`;
}
else {
logger.warn('Setting of access token failed.');
}
});
}
if (!proxyOptions.auth && process.env.FIORI_TOOLS_USER && process.env.FIORI_TOOLS_PASSWORD) {
proxyOptions.auth = `${process.env.FIORI_TOOLS_USER}:${process.env.FIORI_TOOLS_PASSWORD}`;
catch (error) {
logger.warn('Accessing the credentials store failed.');
logger.debug(error);
}
proxyOptions.pathRewrite = exports.PathRewriters.getPathRewrite(backend, logger);
if (backend.bsp) {
yield (0, bsp_1.addOptionsForEmbeddedBSP)(backend.bsp, proxyOptions, logger);
}
if (!proxyOptions.auth && process.env.FIORI_TOOLS_USER && process.env.FIORI_TOOLS_PASSWORD) {
proxyOptions.auth = `${process.env.FIORI_TOOLS_USER}:${process.env.FIORI_TOOLS_PASSWORD}`;
}
proxyOptions.pathRewrite = exports.PathRewriters.getPathRewrite(backend, logger);
if (backend.bsp) {
await (0, bsp_1.addOptionsForEmbeddedBSP)(backend.bsp, proxyOptions, logger);
}
if (backend.apiHub) {
const apiHubKey = await getApiHubKey(logger);
if (apiHubKey) {
proxyOptions.headers['apikey'] = apiHubKey;
}
if (backend.apiHub) {
const apiHubKey = yield getApiHubKey(logger);
if (apiHubKey) {
proxyOptions.headers['apikey'] = apiHubKey;
}
}
if (!proxyOptions.target) {
throw new Error(`Unable to determine target from configuration:\n${JSON.stringify(backend, null, 2)}`);
}
// update proxy config with values coming from args or ui5.yaml
(0, config_1.updateProxyEnv)(backend.proxy);
backend.proxy = (0, proxy_from_env_1.getProxyForUrl)(proxyOptions.target);
if (backend.proxy) {
proxyOptions.agent = new https_proxy_agent_1.HttpsProxyAgent(backend.proxy);
}
logger.info(`Backend proxy created for ${proxyOptions.target} ${backend.path ? backend.path : ''}`);
return proxyOptions;
});
}
if (!proxyOptions.target) {
throw new Error(`Unable to determine target from configuration:\n${JSON.stringify(backend, null, 2)}`);
}
// update proxy config with values coming from args or ui5.yaml
(0, config_1.updateProxyEnv)(backend.proxy);
backend.proxy = (0, proxy_from_env_1.getProxyForUrl)(proxyOptions.target);
if (backend.proxy) {
proxyOptions.agent = new https_proxy_agent_1.HttpsProxyAgent(backend.proxy);
}
logger.info(`Backend proxy created for ${proxyOptions.target} ${backend.path ? backend.path : ''}`);
return proxyOptions;
}

@@ -376,8 +357,6 @@ exports.generateProxyMiddlewareOptions = generateProxyMiddlewareOptions;

*/
function createProxy(backend, options, logger) {
return __awaiter(this, void 0, void 0, function* () {
return (0, http_proxy_middleware_1.createProxyMiddleware)(yield generateProxyMiddlewareOptions(backend, options, logger));
});
async function createProxy(backend, options, logger) {
return (0, http_proxy_middleware_1.createProxyMiddleware)(await generateProxyMiddlewareOptions(backend, options, logger));
}
exports.createProxy = createProxy;
//# sourceMappingURL=proxy.js.map
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {

@@ -37,54 +28,52 @@ return (mod && mod.__esModule) ? mod : { "default": mod };

*/
function promptUserPass(log) {
return __awaiter(this, void 0, void 0, function* () {
if ((0, btp_utils_1.isAppStudio)()) {
const { authNeeded } = yield (0, prompts_1.default)([
{
type: 'confirm',
name: 'authNeeded',
message: `${(0, chalk_1.cyan)(i18next_1.default.t('info.authNeeded'))}\n\n`
}
]);
if (!authNeeded) {
return undefined;
async function promptUserPass(log) {
if ((0, btp_utils_1.isAppStudio)()) {
const { authNeeded } = await (0, prompts_1.default)([
{
type: 'confirm',
name: 'authNeeded',
message: `${(0, chalk_1.cyan)(i18next_1.default.t('info.authNeeded'))}\n\n`
}
]);
if (!authNeeded) {
return undefined;
}
else {
log.info((0, chalk_1.yellow)(i18next_1.default.t('info.credentialsRequiredForFLP')));
}
const { username, password } = yield (0, prompts_1.default)([
{
type: 'text',
name: 'username',
message: `${(0, chalk_1.cyan)(i18next_1.default.t('info.username'))}\n\n`,
validate: (value) => {
if (!(value === null || value === void 0 ? void 0 : value.trim())) {
return `${i18next_1.default.t('error.emptyUsername')}`;
}
else {
return true;
}
}
else {
log.info((0, chalk_1.yellow)(i18next_1.default.t('info.credentialsRequiredForFLP')));
}
const { username, password } = await (0, prompts_1.default)([
{
type: 'text',
name: 'username',
message: `${(0, chalk_1.cyan)(i18next_1.default.t('info.username'))}\n\n`,
validate: (value) => {
if (!value?.trim()) {
return `${i18next_1.default.t('error.emptyUsername')}`;
}
},
{
type: 'password',
name: 'password',
message: `${(0, chalk_1.cyan)(i18next_1.default.t('info.password'))}\n\n`,
validate: (value) => {
if (!(value === null || value === void 0 ? void 0 : value.trim())) {
return `${i18next_1.default.t('error.emptyPassword')}`;
}
else {
return true;
}
else {
return true;
}
}
], {
onCancel: () => {
log.info((0, chalk_1.yellow)(i18next_1.default.t('info.operationAborted')));
return process.exit(1);
},
{
type: 'password',
name: 'password',
message: `${(0, chalk_1.cyan)(i18next_1.default.t('info.password'))}\n\n`,
validate: (value) => {
if (!value?.trim()) {
return `${i18next_1.default.t('error.emptyPassword')}`;
}
else {
return true;
}
}
});
return `${username}:${password}`;
}
], {
onCancel: () => {
log.info((0, chalk_1.yellow)(i18next_1.default.t('info.operationAborted')));
return process.exit(1);
}
});
return `${username}:${password}`;
}

@@ -99,28 +88,26 @@ exports.promptUserPass = promptUserPass;

*/
function addOptionsForEmbeddedBSP(bspPath, proxyOptions, logger) {
return __awaiter(this, void 0, void 0, function* () {
const regex = new RegExp('(' + bspPath + '/manifest\\.appdescr\\b)');
proxyOptions.router = (req) => {
// redirects the request for manifest.appdescr to localhost
if (req.path.match(regex)) {
return req.protocol + '://' + req.headers.host;
}
else {
return undefined;
}
};
if (proxyOptions.pathRewrite) {
const oldRewrite = proxyOptions.pathRewrite;
const appDescrRewrite = convertAppDescriptorToManifest(bspPath);
proxyOptions.pathRewrite = (path) => appDescrRewrite(oldRewrite(path));
async function addOptionsForEmbeddedBSP(bspPath, proxyOptions, logger) {
const regex = new RegExp('(' + bspPath + '/manifest\\.appdescr\\b)');
proxyOptions.router = (req) => {
// redirects the request for manifest.appdescr to localhost
if (req.path.match(regex)) {
return req.protocol + '://' + req.headers.host;
}
else {
proxyOptions.pathRewrite = convertAppDescriptorToManifest(bspPath);
return undefined;
}
if (!proxyOptions.auth) {
proxyOptions.auth = yield promptUserPass(logger);
}
});
};
if (proxyOptions.pathRewrite) {
const oldRewrite = proxyOptions.pathRewrite;
const appDescrRewrite = convertAppDescriptorToManifest(bspPath);
proxyOptions.pathRewrite = (path) => appDescrRewrite(oldRewrite(path));
}
else {
proxyOptions.pathRewrite = convertAppDescriptorToManifest(bspPath);
}
if (!proxyOptions.auth) {
proxyOptions.auth = await promptUserPass(logger);
}
}
exports.addOptionsForEmbeddedBSP = addOptionsForEmbeddedBSP;
//# sourceMappingURL=bsp.js.map
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {

@@ -42,16 +33,18 @@ return (mod && mod.__esModule) ? mod : { "default": mod };

*/
module.exports = ({ options }) => __awaiter(void 0, void 0, void 0, function* () {
var _a;
module.exports = async ({ options }) => {
const logger = new logger_1.ToolsLogger({
transports: [new logger_1.UI5ToolingTransport({ moduleName: 'backend-proxy-middleware' })]
});
yield (0, proxy_1.initI18n)();
await (0, proxy_1.initI18n)();
dotenv_1.default.config();
const backend = options.configuration.backend;
const configOptions = (_a = options.configuration.options) !== null && _a !== void 0 ? _a : {};
const configOptions = options.configuration.options ?? {};
configOptions.secure = configOptions.secure !== undefined ? !!configOptions.secure : true;
try {
const proxyOptions = yield (0, proxy_1.generateProxyMiddlewareOptions)(options.configuration.backend, configOptions, logger);
const proxyOptions = await (0, proxy_1.generateProxyMiddlewareOptions)(options.configuration.backend, configOptions, logger);
const proxyFn = (0, http_proxy_middleware_1.createProxyMiddleware)(proxyOptions);
logger.info(`Starting backend-proxy-middleware using following configuration:\nbackend: ${JSON.stringify(Object.assign(Object.assign({}, backend), { proxy: formatProxyForLogging(backend.proxy) }))}\noptions: ${JSON.stringify(configOptions)}'`);
logger.info(`Starting backend-proxy-middleware using following configuration:\nbackend: ${JSON.stringify({
...backend,
proxy: formatProxyForLogging(backend.proxy)
})}\noptions: ${JSON.stringify(configOptions)}'`);
return (req, res, next) => {

@@ -71,3 +64,3 @@ if (req.path.startsWith(backend.path)) {

}
});
};
//# sourceMappingURL=middleware.js.map

@@ -12,3 +12,3 @@ {

},
"version": "0.7.41",
"version": "0.8.1",
"license": "Apache-2.0",

@@ -32,6 +32,6 @@ "author": "@SAP/ux-tools-team",

"proxy-from-env": "1.1.0",
"@sap-ux/axios-extension": "1.14.4",
"@sap-ux/btp-utils": "0.14.4",
"@sap-ux/logger": "0.5.1",
"@sap-ux/store": "0.6.0"
"@sap-ux/axios-extension": "1.15.1",
"@sap-ux/btp-utils": "0.15.0",
"@sap-ux/logger": "0.6.0",
"@sap-ux/store": "0.7.0"
},

@@ -38,0 +38,0 @@ "devDependencies": {

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc