Skip to content

Writing a Websocket Proxy Middleware for ui5-server #518

@LukasHeimann

Description

@LukasHeimann

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions