[RFC] 0003 Proxy capabilities of ui5-server by RandomByte · Pull Request #41 · UI5/cli

Hi @RandomByte,

I'm trying to build a proxy that can cover websockets as well. This may be just lacking in the documentation, but I have a feeling like this isn't possible with middlewares today.

My middleware 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 valide (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 });
});

As I'd still like to proxy normal requests as well, I'd still have a "proper" middleware to return and would just add that snippet, given that I'd have a reference to the http server and the plugin's mount path.

If there is a way to do this right now with middlewares, I'd like to hear about it, but it seems to not fit their design.

Maybe, what's needed would be a different thing to return:

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 valide (internal) certificates
    });

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

    return {
        middleware: function (req, res, next) {
            const proxyTarget = url.resolve(options.configuration.url, req.path);
            proxy.web(req, res, { target: proxyTarget });
            return;
        },
        // ui5 cli would register on upgrade for me, already filtering so I only receive events for my mountPath
        upgrade: function (req, socket, head) {
            const proxyTarget = url.resolve(options.configuration.url, req.path);
            proxy.ws(req, socket, head, { target: proxyTarget });
        })
    };
};

Thanks for helping me out here!
Kind regards
Lukas