http-proxy-middleware
http-proxy-middleware copied to clipboard
express.use(path, proxy()) ignores path for websockets
Also see expressjs/express#3428.
Expected behavior
The following should listen for websocket requests only under /__webpack_hmr
.
express.use('/__webpack_hmr', proxy({ ws: true, target: 'http://...' }));
Websocket requests to other paths (e.g. /socket.io
) should not be handled by the proxy.
Actual behavior
The proxy "hijacks" all incoming websocket requests, also those to /socket.io
(see socketio/socket.io#3062).
Setup
Fiddle: https://github.com/ftes/socket.io-fiddle/pull/1/files
- http-proxy-middleware: 0.17.4
- server: express 4.13.4
- socket.io: 2.0.3
proxy middleware configuration
proxy({ ws: true, target: 'http://localhost:4000' });
server mounting
var app = express();
app.use('/__webpack_hmr', proxy);
app.listen(3000);
Workaround
Pass path /__webpack_hmr
as context to proxy.
const webpackHmrProxy = proxy('/__webpack_hmr', {
target: 'http://localhost:4000',
ws: true,
});
app.use(webpackHmrProxy);
Thanks for reporting this @ftes . I'll have to investigate this.
I'm having the same issue.. I kinda fixed it passing the "context" twice:
express.use('/__webpack_hmr', proxy('/__webpack_hmr', { ws: true, target: 'http://...' }))
@ftes give it a try.
Slightly off topic:
@roccomuso You don't need the first occurrence of "context" (passed to express.use
) though do you?
I would have thought it would work the same (with or without passing context to express.use
), but for some reason, when I pass the context in both ways, and I restart the server, reconnection in the browser fails with WebSocket connection to 'ws://localhost:3000/api/socket.io/?EIO=3&transport=websocket' failed: Connection closed before receiving a handshake response
even after I refresh the page. If I only pass the context to proxy
then I get those errors only until I refresh the page. My head hurts. No idea what's going on.
I'm experiencing a similar issue.
Where:
app.use("/example", proxy({ target: "www.example.com" }))
Gives:
[HPM] Proxy created: / -> http://www.example.com
And
app.use(proxy("/example", { target: "www.example.com" }))
Gives:
[HPM] Proxy created: /example -> http://www.example.com
"node": "8.9.0"
"express": "^4.16.2",
"http-proxy-middleware": "^0.17.4",
Just wanted to put it here since the README example describes it as the first one...
Oh my god, thanks @roccomuso!
I was using this code which was working fine when the socket had a successful connection but was throwing an error when the WS_URI was returning an error (404, 500 ...)
server.use(proxy("/ws", {
target: process.env.WS_URI,
ws: true
})
);
I just updated my code with this code and it worked. The second route in the proxy method doesn't seem to be required though. I didn't see my route was not handled by express...
server.use("/ws", proxy("/ws", {
target: process.env.WS_URI,
ws: true
})
);
I have the same issue., BUT http-proxy-middleware WORKS when I proxy traffic from "/".
In the broken case, HTTP traffic routes through the proxy, but the proxy fails to upgrade to websockets.
Here is my use() statement. it appears before all other use() statements.:
let wsProxy = Proxy( '/shadowStone', {
ws: true,
target: 'ws://127.0.0.1:3000',
pathRewrite: {
'^/shadowStone': '',
},
logLevel: 'debug',
});
app.use( '/shadowStone', wsProxy );
And, just in case, right after the server.listen() I have put:
server.on('upgrade', wsProxy.upgrade)
The error I am seeing is:
404 error attempting to reach
?EIO=3&transport=polling&t=MgVfhrd
/socket.io
And a later use() statement reports that it is seeing the following:
GET /socket.io/?EIO=3&transport=polling&t=MgVfhrd
When I change my code to read as follows, it WORKS just fine:
let wsProxy = Proxy( '/', {
ws: true,
target: 'ws://127.0.0.1:3000',
// pathRewrite: {
// '^/shadowStone': '',
// },
logLevel: 'debug',
})
app.use( '/', wsProxy );
I found my issue. I was using socket.io, which is very particular about how you initialize it. In the target of the proxy, in index.html, I was starting socket.io with:
this.socket = io.connect('http://localhost:3000/shadowStone');
when I should have been starting it with:
this.socket = io.connect('http://localhost:3000', {'path': '/shadowStone/socket.io'});
and the server-side companion code to this is
app.use( '/shadowStone', Express.static('.') )
let server = app.listen(3000)
io = SocketIo(server, {path:'/shadowStone/socket.io'});
In my proxy, the code is quite simple:
let wsProxy = Proxy({
target: 'ws://localhost:3000',
logLevel: 'debug',
});
app.use( '/shadowStone', wsProxy );
let server = app.listen(port);
server.on('upgrade', wsProxy.upgrade)
Hope this helps somebody with a similar problem...
Is there any workaround for this in current version? I'm trying to proxy WS to my server in create-react-app without breaking reloader that listens on different path.
I've changed this:
module.exports = function(app) {
app.use(
'/sockjs-node',
createProxyMiddleware(
{
target: 'ws://localhost:3000',
ws: true,
}
)
);
app.use(
'/graphql',
createProxyMiddleware(
{
target: 'http://localhost:8000',
changeOrigin: true,
ws: true,
}
)
);
};
to this:
module.exports = function(app) {
app.use(
'/sockjs-node',
createProxyMiddleware(
'/sockjs-node',
{
target: 'ws://localhost:3000',
ws: true,
}
)
);
app.use(
'/graphql',
createProxyMiddleware(
'/graphql',
{
target: 'http://localhost:8000',
changeOrigin: true,
ws: true,
}
)
);
};
...and its working now :)