@fontoxml/fontoxml-development-tools
Version:
Development tools for Fonto.
111 lines (93 loc) • 3.24 kB
JavaScript
import express from 'express';
import { createProxyMiddleware } from 'http-proxy-middleware';
import typeIs from 'type-is';
import configureBodyParserMiddleware from './configureBodyParserMiddleware.js';
import correlationIdRepository from './correlationIdRepository.js';
/** @typedef {import('../../src/getAppConfig.js').DevCmsConfig} DevCmsConfig */
function getEditSessionToken(req) {
if (req.query && req.query.context) {
if (req.query.context.editSessionToken) {
return req.query.context.editSessionToken;
}
try {
const context = JSON.parse(req.query.context);
if (context && context.editSessionToken) {
return context.editSessionToken;
}
} catch (_error) {
// Could not parse context as JSON, so ignore.
}
}
if (req.body && req.body.context && req.body.context.editSessionToken) {
// Use the edit session token from the request body. This is not supported for multi-part requests.
// TODO: Should we support this on multi-part requests?
return req.body.context.editSessionToken;
}
return undefined;
}
function requestHasJsonBody(req) {
return !!typeIs(req, ['application/json']);
}
/**
* @param {DevCmsConfig} config
*/
function configureConnectorsCmsStandardProxyRouter(config) {
// eslint-disable-next-line new-cap
const connectorsCmsStandardProxyRouter = express.Router();
const bodyParserMiddleware = configureBodyParserMiddleware(config);
// Create the Proxy middleware.
const proxyCurrentRequest = createProxyMiddleware({
// Custom router function with the target object.
router(req) {
const proxyName = req.params.proxyName;
return config.proxy[proxyName];
},
secure: false,
changeOrigin: true,
logger: {
error: console.error.bind(console),
warn: console.warn.bind(console),
info: () => undefined,
},
on: {
proxyReq: (proxyReq, req, _res) => {
const editSessionToken = getEditSessionToken(req);
const correlationId =
correlationIdRepository.createNewWithAllRequestsAsValidValidator(
editSessionToken,
);
proxyReq.setHeader('Fonto-Correlation-Id', correlationId);
if (requestHasJsonBody(req) && req.body) {
// Write the JSON body to the proxied request, update the content-length header
// to account for any stringify/prettify differences, and remove the
// content-encoding header if there is one as we are forwarding without encoding.
const body = JSON.stringify(req.body);
proxyReq.removeHeader('content-encoding');
proxyReq.setHeader('content-length', Buffer.byteLength(body));
proxyReq.write(body);
proxyReq.end();
}
},
proxyRes: (proxyRes, _req, _res) => {
correlationIdRepository.delete(
proxyRes.req.getHeader('Fonto-Correlation-Id'),
);
},
},
});
connectorsCmsStandardProxyRouter.use(
'/connectors/cms/standard/proxy/:proxyName/',
(req, res, next) => {
if (requestHasJsonBody(req)) {
// Parse JSON body to try and get the editSessionToken.
bodyParserMiddleware(req, res, () => {
proxyCurrentRequest(req, res, next);
});
} else {
proxyCurrentRequest(req, res, next);
}
},
);
return connectorsCmsStandardProxyRouter;
}
export default configureConnectorsCmsStandardProxyRouter;