next-http-proxy-middleware
next-http-proxy-middleware copied to clipboard
Proxy websockets
I'm trying to use this library to proxy websockets. I've tried several approaches but so far none of them are working.
import { NextApiRequest, NextApiResponse } from "next";
import httpProxyMiddleware from "next-http-proxy-middleware";
export const config = {
api: {
bodyParser: false,
externalResolver: true,
},
};
export default async (req: NextApiRequest, res: NextApiResponse) => {
return httpProxyMiddleware(req, res, {
target: "ws://localhost:3001/graphql",
ws: true,
});
};
Is it possible to do it with this library?
Hi @Kerumen It seems to force NextJS to remove the slash (/) at the end of the URL if the API URL path contains a '.'. In my case, the ws connection was successful using socketio.
Try this
// [...all.ts]
export default async (req: NextApiRequest, res: NextApiResponse) => {
return httpProxyMiddleware(req, res, {
target: "ws://localhost:3000",
ws: true,
pathRewrite: [
{
patternStr: '^/api',
replaceStr: '',
},
],
}
};
// frontend code
...
const socket = io('localhost:3000', {
path: 'socketio' // < (important) do not include `.` character in pathname
});
...
// ws server
...
var io = require('socket.io')(server, {
path: '/socketio' // < The same name as the socketio instance configuration pathname on the frontend
});
...
thanks 😀
Thanks for your reply. I don't have any .
in my URL. In fact, the URL is the same between the normal HTTP endpoint and for the WebSocket endpoint (it's /graphql
).
I'm using the following pathRewrite
:
pathRewrite: [
{
patternStr: "^/api",
replaceStr: "",
},
],
And on the frontend, I'm trying to connect with Apollo WS (the HTTP link with the proxy is working).
Thanks for your reply. I don't have any
.
in my URL. In fact, the URL is the same between the normal HTTP endpoint and for the WebSocket endpoint (it's/graphql
).I'm using the following
pathRewrite
:pathRewrite: [ { patternStr: "^/api", replaceStr: "", }, ],
And on the frontend, I'm trying to connect with Apollo WS (the HTTP link with the proxy is working).
the NextJs API does not seem to recognize the ws
scheme because it does an http proxy.
Looks like apollo client should support a mechanism to upgrade http protocol to ws.
- reference
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism#upgrading_http1.1_connections
- https://socket.io/docs/v3/how-it-works/#upgrade-mechanism
The picture below is an error message when I put the http scheme in the graphql-ws library.
Please let me know if I'm misunderstanding anything.
I don't understand what you tried here. My use case is very simple: I have a Next.js API route which is basically the proxy:
// pages/api/graphql.ts
export const config = {
api: {
bodyParser: false,
externalResolver: true,
},
};
export default async (req: NextApiRequest, res: NextApiResponse) => {
return httpProxyMiddleware(req, res, {
target: "http://localhost:3001/graphql",
pathRewrite: [
{
patternStr: "^/api",
replaceStr: "",
},
],
});
};
On the frontend I have the Apollo's HTTP link:
new HttpLink({
uri: "http://localhost:3000/api/graphql",
credentials: "include",
headers,
});
This setup is working fine. I'm trying to replicate it for WS:
export default async (req: NextApiRequest, res: NextApiResponse) => {
return httpProxyMiddleware(req, res, {
ws: true,
target: "ws://localhost:3001/graphql",
pathRewrite: [
{
patternStr: "^/api",
replaceStr: "",
},
],
});
};
And on the frontend, with the WS link:
new WebSocketLink({
uri: "ws://localhost:3000/api/graphql",
options: {
reconnect: true,
},
});
And it tries to connect in loop without success.
Side note, if i change the WebSocketLink
's uri
and directly set the backend endpoint (ws://localhost:3001/graphql
) it works. Hence, it's not a problem with Apollo but rather with the proxy itself.
I don't understand what you tried here. My use case is very simple: I have a Next.js API route which is basically the proxy:
In my case i used graphql-ws/createClient
client
// client
import { createClient } from 'graphql-ws';
...
const client = createClient({
url: 'http://localhost:3000/api/graphql',
});
(async () => {
const result = await new Promise((resolve, reject) => {
let result;
client.subscribe(
{
query: '{ hello }',
},
{
next: (data) => (result = data),
error: reject,
complete: () => resolve(result),
},
);
});
// server
const { GraphQLSchema, GraphQLObjectType, GraphQLString } = require('graphql');
const { WebSocketServer } = require('ws');
const { useServer } = require('graphql-ws/lib/use/ws');
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
hello: {
type: GraphQLString,
resolve: () => 'world',
},
},
}),
subscription: new GraphQLObjectType({
name: 'Subscription',
fields: {
greetings: {
type: GraphQLString,
subscribe: async function* () {
for (const hi of ['Hi', 'Bonjour', 'Hola', 'Ciao', 'Zdravo']) {
yield { greetings: hi };
}
},
},
},
}),
});
const server = new WebSocketServer({
port: 4000,
path: '/graphql',
});
useServer({ schema }, server);
console.log('Listening to port 4000');
--
If the problem is still not resolved, could you please share the server/client sample source code on Stackblitz or Github repository?
did you end up solving this ? i'm having same issue of getting proxy to resolve...
Unsolved to date, nextjs has a big problem with websocket support in reverse proxy. I managed to make it work but after a few refreshes the connection drops and it only works again by restarting
@murilob1337 can you share code you got to work? I am deciding whether to throw out this path and just do a nginx frontend ... complicates development environment but pulling my hair out here
I gave up for now and deleted the old code because there was no way for it to work perfectly, I made a reverse proxy only on the endpoint that does not have websocket and the one that has ws I put it on another port. I went through this friend, I thought about abandoning nextjs because of this
just make a standalone node server for this. unfortunately nextjs doesnt seem to help with websockets much
This library is dependent on Next.js. Therefore, unless Next.js supports WebSocket communication methods, we cannot implement WebSocket communication.