From 4170418612505945c3c9295019c70725774efd78 Mon Sep 17 00:00:00 2001 From: James Bain Date: Mon, 10 Jun 2024 18:57:31 -0600 Subject: [PATCH 1/3] #333 fix: allow for websockets when loading plugin --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index ad52b9e..16cf0e8 100644 --- a/index.js +++ b/index.js @@ -229,7 +229,7 @@ function generateRewritePrefix (prefix, opts) { } async function fastifyHttpProxy (fastify, opts) { - if (!opts.upstream && !(opts.upstream === '' && opts.replyOptions && typeof opts.replyOptions.getUpstream === 'function')) { + if (!opts.upstream && !opts.websocket && !((opts.upstream === '' || opts.wsUpstream === '') && opts.replyOptions && typeof opts.replyOptions.getUpstream === 'function')) { throw new Error('upstream must be specified') } From c0a3d9d021064685f6b2404a5a6ef1147e13d0e9 Mon Sep 17 00:00:00 2001 From: James Bain Date: Tue, 11 Jun 2024 11:03:33 -0600 Subject: [PATCH 2/3] #333 fix: add ternary check for upstream to WebsocketProxyConstructor --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 16cf0e8..0e4667a 100644 --- a/index.js +++ b/index.js @@ -97,7 +97,7 @@ class WebSocketProxy { headers: {}, ...wsClientOptions } - this.upstream = convertUrlToWebSocket(upstream) + this.upstream = upstream ? convertUrlToWebSocket(upstream) : '' this.wsUpstream = wsUpstream ? convertUrlToWebSocket(wsUpstream) : '' this.getUpstream = getUpstream From e2e702ff36f3478e8db4be546672dfb063dcd7f6 Mon Sep 17 00:00:00 2001 From: James Bain Date: Tue, 11 Jun 2024 11:04:22 -0600 Subject: [PATCH 3/3] #333 test: add a test for getUpstream with empty wsUpstream set --- test/websocket.js | 68 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/test/websocket.js b/test/websocket.js index a711895..50bb067 100644 --- a/test/websocket.js +++ b/test/websocket.js @@ -194,6 +194,74 @@ test('getUpstream', async (t) => { ]) }) +test('getUpstream with unset wsUpstream', async (t) => { + t.plan(9) + + const origin = createServer() + const wss = new WebSocket.Server({ server: origin }) + t.teardown(wss.close.bind(wss)) + t.teardown(origin.close.bind(origin)) + + const serverMessages = [] + wss.on('connection', (ws, request) => { + t.equal(ws.protocol, subprotocolValue) + t.equal(request.headers.cookie, cookieValue) + ws.on('message', (message, binary) => { + serverMessages.push([message.toString(), binary]) + // echo + ws.send(message, { binary }) + }) + }) + + await promisify(origin.listen.bind(origin))({ port: 0, host: '127.0.0.1' }) + + const server = Fastify() + + let _req + server.server.on('upgrade', (req) => { + _req = req + }) + + server.register(proxy, { + wsUpstream: '', + replyOptions: { + getUpstream: function (original) { + t.not(original, _req) + t.equal(original.raw, _req) + return `http://127.0.0.1:${origin.address().port}` + } + }, + websocket: true + }) + + await server.listen({ port: 0, host: '127.0.0.1' }) + t.teardown(server.close.bind(server)) + + const options = { headers: { cookie: cookieValue } } + const ws = new WebSocket(`ws://127.0.0.1:${server.server.address().port}`, [subprotocolValue], options) + await once(ws, 'open') + + ws.send('hello', { binary: false }) + const [reply0, binary0] = await once(ws, 'message') + t.equal(reply0.toString(), 'hello') + t.equal(binary0, false) + + ws.send(Buffer.from('fastify'), { binary: true }) + const [reply1, binary1] = await once(ws, 'message') + t.equal(reply1.toString(), 'fastify') + t.equal(binary1, true) + + t.strictSame(serverMessages, [ + ['hello', false], + ['fastify', true] + ]) + + await Promise.all([ + once(ws, 'close'), + server.close() + ]) +}) + test('websocket proxy trigger hooks', async (t) => { t.plan(8)