Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added proxy support #152

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ The development server has already a set of middlewares which supports the devel
* Version info is created automatically (`/resources/sap-ui-version.json`).
* List project files with URL (needed exclusively by the OpenUI5 testsuite): `/discovery/app_pages`, `/discovery/all_libs`, `/discovery/all_tests`

### Proxy requests
A neo-app.json and neo-dest.json file can be added to the project and used to proxy requests to an SAP gateway server for example. When you create your UI5 serve you need to add the path to the neo files.
The neo-app.json file can be reused from a WebIDE template, the neo-dest.json file is a json object that has the target name and the following attributes is available
* target : Target url
* Authentication : Authentication method, currently only basic is supported
* User : Username
* Password : Password for the proxy request
* sapclient : SAP Client

## Certificates for HTTPS or HTTP/2
The UI5 Server can automatically generate an SSL certificate for HTTPS and HTTP/2 configurations.

Expand Down
57 changes: 56 additions & 1 deletion lib/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ const nonReadRequests = require("./middleware/nonReadRequests");
const ui5Fs = require("@ui5/fs");
const resourceFactory = ui5Fs.resourceFactory;
const ReaderCollectionPrioritized = ui5Fs.ReaderCollectionPrioritized;
const proxy = require("http-proxy-middleware");
const noCache = require("nocache");

/**
* Returns a promise resolving by starting the server.
Expand Down Expand Up @@ -104,13 +106,19 @@ module.exports = {
* @param {string} [options.cert] Path to certificate to be used for for https
* @param {boolean} [options.acceptRemoteConnections=false] If true, listens to remote connections and
* not only to localhost connections
* @param {Object} [options.neoApp] an JSON object that has the routes for proxy
* @param {Object} [options.destinations] Json object with the destination attributes for proxy
* @returns {Promise<Object>} Promise resolving once the server is listening.
* It resolves with an object containing the <code>port</code>,
* <code>h2</code>-flag and a <code>close</code> function,
* which can be used to stop the server.
*/
serve(tree, {port, changePortIfInUse = false, h2 = false, key, cert, acceptRemoteConnections = false}) {
serve(tree, {port, changePortIfInUse = false, h2 = false, key, cert, acceptRemoteConnections = false, neoApp, destinations}) {
return Promise.resolve().then(() => {
// Load the neo-app.json and the neo-dest.json file
const oNeoApp = neoApp;
const oDestinations = destinations;

const projectResourceCollections = resourceFactory.createCollectionsForTree(tree);

const workspace = resourceFactory.createWorkspace({
Expand Down Expand Up @@ -170,6 +178,53 @@ module.exports = {
secure: false
}));

// no odata cache (including metadata)
app.use("/sap/opu", noCache());

// Proxy the neo-app.json and neo-dest.json files
if (oNeoApp && oNeoApp.routes) {
oNeoApp.routes.forEach(function(oRoute) {
const oTarget = oRoute.target;
if (oTarget) {
// proxy options
const oOptions = {};
// search for destination
if (oDestinations && oTarget.name) {
const oDestination = oDestinations[oTarget.name];
if (oDestination) {
oOptions.target = oDestination.target;
oOptions.changeOrigin = true;
oOptions.secure = false;
/* if (oDestination.useProxy) {
oOptions.agent = oAgent;
}*/

// Added support for client and basic authentication
if (oDestination.sapclient) {
oOptions.onProxyReq = function onProxyReq(proxyReq, req, res) {
req.originalUrl = req.originalUrl + "&sap-client=" +oDestination.sapclient;
};
}

if (oDestination.Authentication === "Basic") {
oOptions.headers = {
"Authorization": "Basic " + Buffer.from(oDestination.User +
":" + oDestination.Password).toString("base64")
};
}
}
}
if (oRoute.path && oTarget.entryPath) {
const oRouteNew = {};
const sPathOld = "^" + oRoute.path;
oRouteNew[sPathOld] = oTarget.entryPath;
oOptions.pathRewrite = oRouteNew;
}
app.use(oRoute.path, proxy(oOptions));
}
});
}

// Handle anything but read operations *before* the serveIndex middleware
// as it will reject them with a 405 (Method not allowed) instead of 404 like our old tooling
app.use(nonReadRequests({resourceCollections}));
Expand Down
Loading