Skip to content

Commit e140fdd

Browse files
fix: websocket upstream with rewrite prefix (#389)
1 parent 0c49029 commit e140fdd

File tree

2 files changed

+71
-3
lines changed

2 files changed

+71
-3
lines changed

index.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,12 +150,11 @@ class WebSocketProxy {
150150
}
151151

152152
findUpstream (request, dest) {
153-
const { search, pathname } = new URL(request.url, 'ws://127.0.0.1')
153+
const { search } = new URL(request.url, 'ws://127.0.0.1')
154154

155155
if (typeof this.wsUpstream === 'string' && this.wsUpstream !== '') {
156-
const target = new URL(this.wsUpstream)
156+
const target = new URL(dest, this.wsUpstream)
157157
target.search = search
158-
target.pathname = target.pathname === '/' ? pathname : target.pathname
159158
return target
160159
}
161160

test/websocket.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,75 @@ test('Proxy websocket with custom upstream url', async (t) => {
543543
])
544544
})
545545

546+
test('Proxy websocket with custom upstream url', async (t) => {
547+
t.plan(5)
548+
549+
const origin = createServer()
550+
const wss = new WebSocket.Server({ server: origin })
551+
552+
t.teardown(wss.close.bind(wss))
553+
t.teardown(origin.close.bind(origin))
554+
555+
const serverMessages = []
556+
wss.on('connection', (ws, request) => {
557+
ws.on('message', (message, binary) => {
558+
// Also need save request.url for check from what url the message is coming.
559+
serverMessages.push([message.toString(), binary, request.headers.host.split(':', 1)[0], request.url])
560+
ws.send(message, { binary })
561+
})
562+
})
563+
564+
await promisify(origin.listen.bind(origin))({ port: 0, host: '127.0.0.1' })
565+
// Host for wsUpstream and for later check.
566+
const host = '127.0.0.1'
567+
// Path for wsUpstream and for later check.
568+
const prefix = '/prefix'
569+
const rewritePrefix = '/rewrite'
570+
const server = Fastify()
571+
server.register(proxy, {
572+
prefix,
573+
rewritePrefix,
574+
wsUpstream: `ws://${host}:${origin.address().port}`,
575+
websocket: true
576+
})
577+
578+
await server.listen({ port: 0, host: '127.0.0.1' })
579+
t.teardown(server.close.bind(server))
580+
581+
const path = '/some/path'
582+
// Start websocket with different upstream for connect, added path.
583+
const ws = new WebSocket(`ws://${host}:${server.server.address().port}${prefix}${path}`)
584+
await once(ws, 'open')
585+
586+
const data = [{ message: 'hello', binary: false }, { message: 'fastify', binary: true, isBuffer: true }]
587+
const dataLength = data.length
588+
let dataIndex = 0
589+
590+
for (; dataIndex < dataLength; dataIndex++) {
591+
const { message: msg, binary, isBuffer } = data[dataIndex]
592+
const message = isBuffer
593+
? Buffer.from(msg)
594+
: msg
595+
596+
ws.send(message, { binary })
597+
598+
const [reply, binaryAnswer] = await once(ws, 'message')
599+
600+
t.equal(reply.toString(), msg)
601+
t.equal(binaryAnswer, binary)
602+
}
603+
// Also check "path", must be the same.
604+
t.strictSame(serverMessages, [
605+
['hello', false, host, rewritePrefix + path],
606+
['fastify', true, host, rewritePrefix + path]
607+
])
608+
609+
await Promise.all([
610+
once(ws, 'close'),
611+
server.close()
612+
])
613+
})
614+
546615
test('multiple websocket upstreams with host constraints', async (t) => {
547616
t.plan(4)
548617

0 commit comments

Comments
 (0)