Skip to content

Commit 83f81be

Browse files
committed
fix: match upgrade requests correctly in node.js
1 parent c81630d commit 83f81be

3 files changed

Lines changed: 100 additions & 2 deletions

File tree

src/core/ws.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { invariant } from 'outvariant'
2-
import { FetchResponse } from '@mswjs/interceptors'
2+
import { FetchResponse, resolveWebSocketUrl } from '@mswjs/interceptors'
33
import type {
44
WebSocketData,
55
WebSocketClientConnectionProtocol,
@@ -115,7 +115,7 @@ function createWebSocketLinkHandler(url: Path): WebSocketLink {
115115
const upgradeHandler = http.get(({ request }) => {
116116
return (
117117
request.headers.get('upgrade')?.toLowerCase() === 'websocket' &&
118-
matchRequestUrl(new URL(request.url), url).matches
118+
matchRequestUrl(new URL(resolveWebSocketUrl(request.url)), url).matches
119119
)
120120
}, ws.onUpgrade)
121121

@@ -197,6 +197,8 @@ export const ws: WebSocketNamespace = {
197197
const digest = await crypto.subtle.digest('SHA-1', keyBytes)
198198
const acceptValue = btoa(String.fromCharCode(...new Uint8Array(digest)))
199199

200+
new WebSocket(resolveWebSocketUrl(request.url))
201+
200202
return new FetchResponse(null, {
201203
status: 101,
202204
headers: {
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import type { ws } from 'msw'
2+
import type { setupWorker } from 'msw/browser'
3+
import { test, expect } from '../playwright.extend'
4+
5+
declare global {
6+
interface Window {
7+
msw: {
8+
ws: typeof ws
9+
setupWorker: typeof setupWorker
10+
}
11+
}
12+
}
13+
14+
test('', async ({ loadExample, page }) => {
15+
await loadExample(new URL('./ws.runtime.js', import.meta.url), {
16+
skipActivation: true,
17+
})
18+
19+
await page.evaluate(async () => {
20+
const { setupWorker, ws } = window.msw
21+
const service = ws.link('wss://localhost/ws')
22+
23+
const worker = setupWorker(
24+
service.addEventListener('connection', ({ client }) => {
25+
console.log('CONNECTION CALLED!')
26+
client.send('hello world')
27+
}),
28+
)
29+
await worker.start()
30+
})
31+
32+
await page.evaluate(async () => {
33+
await fetch('https://localhost/ws', {
34+
headers: {
35+
upgrade: 'websocket',
36+
},
37+
})
38+
39+
// const socket = new WebSocket('wss://example.com')
40+
// return new Promise<string>((resolve, reject) => {
41+
// socket.onmessage = (event) => resolve(event.data)
42+
// socket.onerror = () => reject(new Error('WebSocket error'))
43+
// }).finally(() => socket.close())
44+
})
45+
})
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// @vitest-environment node
2+
import { ws } from 'msw'
3+
import { setupServer } from 'msw/node'
4+
5+
const server = setupServer()
6+
7+
beforeAll(() => {
8+
server.listen()
9+
})
10+
11+
afterEach(() => {
12+
server.resetHandlers()
13+
})
14+
15+
afterAll(() => {
16+
server.close()
17+
})
18+
19+
it('intercepts a WebSocket connection via an HTTP request upgrade', async () => {
20+
const api = ws.link('wss://localhost/ws')
21+
22+
const connectionListener = vi.fn()
23+
server.use(api.addEventListener('connection', connectionListener))
24+
25+
const upgradeResponse = await fetch('https://localhost/ws', {
26+
headers: {
27+
upgrade: 'websocket',
28+
connection: 'upgrade',
29+
'sec-websocket-key': 'abc-123',
30+
},
31+
})
32+
33+
expect.soft(upgradeResponse.status).toBe(101)
34+
expect.soft(upgradeResponse.headers.get('upgrade')).toBe('websocket')
35+
expect.soft(upgradeResponse.headers.get('connection')).toBe('upgrade')
36+
expect
37+
.soft(upgradeResponse.headers.get('sec-websocket-accept'))
38+
.toBe('apA7rfK383HiPlWh1+EOR3vC9ww=')
39+
40+
await expect
41+
.poll(() => connectionListener)
42+
.toHaveBeenCalledExactlyOnceWith(
43+
expect.objectContaining({
44+
client: expect.objectContaining({
45+
socket: expect.objectContaining({
46+
url: 'wss://localhost/ws',
47+
}),
48+
}),
49+
}),
50+
)
51+
})

0 commit comments

Comments
 (0)