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

Writing a Websocket Proxy Middleware for ui5-server #518

Closed
LukasHeimann opened this issue Apr 29, 2021 · 3 comments
Closed

Writing a Websocket Proxy Middleware for ui5-server #518

LukasHeimann opened this issue Apr 29, 2021 · 3 comments
Labels
enhancement New feature or request module/ui5-server Related to the UI5 Server module

Comments

@LukasHeimann
Copy link

Is your feature request related to a problem? Please describe.

For my project, I want to proxy a backend server into the ui5-app served by ui5 serve. The backend server not only responds to normal HTTP requests, but also supports connections via Websocket -- which is what I want to consume from my UI.

I've searched the issues and documentation and found no mention how proxying for a Websocket can be made possible with a custom middleware.

Describe the solution you'd like

My proxy middleware, at the moment, looks like this:

const url = require('url');
const httpProxy = require('http-proxy');

module.exports = function({resources, options}) {
    const proxy = httpProxy.createProxyServer({
        changeOrigin: true, // change the origin to the target host
        ignorePath: true, // we combine the full target ourselves
        secure: false // don't try to validate (internal) certificates
    });

    proxy.on('error', (err, req, res) => {
        console.error(err);
        res.end(err.message);
    });

    return function backendProxy(req, res, next) {
        const proxyTarget = url.resolve(options.configuration.url, req.path);
        proxy.web(req, res, { target: proxyTarget });
        return;
    }
};

This doesn't cover websockets. As per http-proxy's documentation, you'd need to attach to the httpserver to do that, i.e. (disclaimer: don't know if that'd work):

ui5InternalHttpServer.on('upgrade', function (req, socket, head) {
  // TODO: Check if the middleware's `mountPath` matches -- unknown where to read that from
  const proxyTarget = url.resolve(options.configuration.url, req.path);
  proxy.ws(req, socket, head, { target: proxyTarget });
});

Ideally, the ui5 tooling would provide me with a "managed" way to attach to upgrade events of the underlying http server that affect the mount path of my middleware. This could be made possible either by allowing me to return two functions in my extension (one for normal http requests, one for websockets), or by allowing me to in the existing function distinguish between normal requests and upgrade events (which will be sent to the middleware as well).

As a short-term workaround, directly using the internal http-server would be okay for me as well, but I don't know how I would acquire a reference to it in my extension.

Describe alternatives you've considered

An alternative solution would be to not use any proxy in the ui5 tooling, and rather set up a relaxed cross-origin policy on my development server.

Additional context

When this requirement came up on my side, I've posted this a month ago into #41 (comment), where I thought it fit best. However, there hasn't been any response yet, so I'm starting a fresh discussion here.

@LukasHeimann LukasHeimann added the enhancement New feature or request label Apr 29, 2021
@stefania-santimbrean
Copy link

Hello @LukasHeimann I'm also looking for a way of using websockets with UI5 Tooling. Have you found any alternate way?

@RandomByte RandomByte added the module/ui5-server Related to the UI5 Server module label May 14, 2021
@LukasHeimann
Copy link
Author

Hi @stefania-santimbrean,

I haven't taken the time to debug the UI5 CLI and see what you can actually get from the various parameters to maybe find a way to include a websocket mockserver. I had a brief look into the coding, but doesn't look good for the use case.

The best solution for now seems to be to go around the UI5 tooling and just go directly to the ws-server (running on a different port). I'm not particularly fond of this situation, as my app is to be deployed on the BTP with an approuter, so there would be no need to have a config-flag somewhere with which to change the host (or port) to something else, but for now this is the way...

@LukasHeimann
Copy link
Author

I've had another look at this (prompted by a snippet I saw), and it seems you can not only return a callback, but rather return a fully fledged express middleware (because it is just put into app.use()). This is documented here: https://sap.github.io/ui5-tooling/pages/extensibility/CustomServerMiddleware/#example-basic-configuration

If you are lazy, you can use e.g. https://www.npmjs.com/package/http-proxy-middleware to create the express middleware your custom ui5 serve middleware returns.

If you are even lazier, you can just use https://www.npmjs.com/package/@sap/ux-ui5-tooling#proxying-websockets

My use cases are covered by the sap package, so I'll close this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request module/ui5-server Related to the UI5 Server module
Projects
None yet
Development

No branches or pull requests

3 participants