Skip to content

Commit

Permalink
websocket: add tests for opening handshake (nodejs#1831)
Browse files Browse the repository at this point in the history
* test: add tests for opening handshake

* test: add tests for opening handshake

* fix: run each test separately
  • Loading branch information
KhafraDev authored and crysmags committed Feb 27, 2024
1 parent 694fcff commit 19a758a
Show file tree
Hide file tree
Showing 2 changed files with 240 additions and 0 deletions.
71 changes: 71 additions & 0 deletions test/websocket/diagnostics-channel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
'use strict'

const t = require('tap')
const dc = require('diagnostics_channel')
const { WebSocketServer } = require('ws')
const { WebSocket } = require('../..')

t.test('diagnostics channel', { jobs: 1 }, (t) => {
t.plan(2)

t.test('undici:websocket:open', (t) => {
t.plan(3)

const server = new WebSocketServer({ port: 0 })

server.on('connection', (ws) => {
ws.close(1000, 'goodbye')
})

const listener = ({ extensions, protocol }) => {
t.equal(extensions, null)
t.equal(protocol, 'chat')
}

t.teardown(() => {
dc.channel('undici:websocket:open').unsubscribe(listener)
return server.close()
})

const { port } = server.address()

dc.channel('undici:websocket:open').subscribe(listener)

const ws = new WebSocket(`ws://localhost:${port}`, 'chat')

ws.addEventListener('open', () => {
t.pass('Emitted open')
})
})

t.test('undici:websocket:close', (t) => {
t.plan(4)

const server = new WebSocketServer({ port: 0 })

server.on('connection', (ws) => {
ws.close(1000, 'goodbye')
})

const listener = ({ websocket, code, reason }) => {
t.type(websocket, WebSocket)
t.equal(code, 1000)
t.equal(reason, 'goodbye')
}

t.teardown(() => {
dc.channel('undici:websocket:close').unsubscribe(listener)
return server.close()
})

const { port } = server.address()

dc.channel('undici:websocket:close').subscribe(listener)

const ws = new WebSocket(`ws://localhost:${port}`, 'chat')

ws.addEventListener('close', () => {
t.pass('Emitted open')
})
})
})
169 changes: 169 additions & 0 deletions test/websocket/opening-handshake.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,172 @@ test('Open event is emitted', (t) => {
ws.onmessage = ws.onerror = t.fail
ws.addEventListener('open', t.pass)
})

test('Multiple protocols are joined by a comma', (t) => {
t.plan(1)

const server = new WebSocketServer({ port: 0 })

server.on('connection', (ws, req) => {
t.equal(req.headers['sec-websocket-protocol'], 'chat, echo')

ws.close(1000)
server.close()
})

t.teardown(server.close.bind(server))

const ws = new WebSocket(`ws://localhost:${server.address().port}`, ['chat', 'echo'])

ws.addEventListener('open', () => ws.close())
})

test('Server doesn\'t send Sec-WebSocket-Protocol header when protocols are used', (t) => {
t.plan(1)

const server = createServer((req, res) => {
res.statusCode = 101

req.socket.destroy()
}).listen(0, () => {
const ws = new WebSocket(`ws://localhost:${server.address().port}`, 'chat')

ws.onopen = t.fail

ws.addEventListener('error', ({ error }) => {
t.ok(error)
})
})

t.teardown(server.close.bind(server))
})

test('Server sends invalid Upgrade header', (t) => {
t.plan(1)

const server = createServer((req, res) => {
res.setHeader('Upgrade', 'NotWebSocket')
res.statusCode = 101

req.socket.destroy()
}).listen(0, () => {
const ws = new WebSocket(`ws://localhost:${server.address().port}`)

ws.onopen = t.fail

ws.addEventListener('error', ({ error }) => {
t.ok(error)
})
})

t.teardown(server.close.bind(server))
})

test('Server sends invalid Connection header', (t) => {
t.plan(1)

const server = createServer((req, res) => {
res.setHeader('Upgrade', 'websocket')
res.setHeader('Connection', 'downgrade')
res.statusCode = 101

req.socket.destroy()
}).listen(0, () => {
const ws = new WebSocket(`ws://localhost:${server.address().port}`)

ws.onopen = t.fail

ws.addEventListener('error', ({ error }) => {
t.ok(error)
})
})

t.teardown(server.close.bind(server))
})

test('Server sends invalid Sec-WebSocket-Accept header', (t) => {
t.plan(1)

const server = createServer((req, res) => {
res.setHeader('Upgrade', 'websocket')
res.setHeader('Connection', 'upgrade')
res.setHeader('Sec-WebSocket-Accept', 'abc')
res.statusCode = 101

req.socket.destroy()
}).listen(0, () => {
const ws = new WebSocket(`ws://localhost:${server.address().port}`)

ws.onopen = t.fail

ws.addEventListener('error', ({ error }) => {
t.ok(error)
})
})

t.teardown(server.close.bind(server))
})

test('Server sends invalid Sec-WebSocket-Extensions header', (t) => {
const uid = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
const { createHash } = require('crypto')

t.plan(2)

const server = createServer((req, res) => {
const key = req.headers['sec-websocket-key']
t.ok(key)

const accept = createHash('sha1').update(key + uid).digest('base64')

res.setHeader('Upgrade', 'websocket')
res.setHeader('Connection', 'upgrade')
res.setHeader('Sec-WebSocket-Accept', accept)
res.setHeader('Sec-WebSocket-Extensions', 'InvalidExtension')
res.statusCode = 101

res.end()
}).listen(0, () => {
const ws = new WebSocket(`ws://localhost:${server.address().port}`)

ws.onopen = t.fail

ws.addEventListener('error', ({ error }) => {
t.ok(error)
})
})

t.teardown(server.close.bind(server))
})

test('Server sends invalid Sec-WebSocket-Extensions header', (t) => {
const uid = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
const { createHash } = require('crypto')

t.plan(2)

const server = createServer((req, res) => {
const key = req.headers['sec-websocket-key']
t.ok(key)

const accept = createHash('sha1').update(key + uid).digest('base64')

res.setHeader('Upgrade', 'websocket')
res.setHeader('Connection', 'upgrade')
res.setHeader('Sec-WebSocket-Accept', accept)
res.setHeader('Sec-WebSocket-Protocol', 'echo') // <--
res.statusCode = 101

res.end()
}).listen(0, () => {
const ws = new WebSocket(`ws://localhost:${server.address().port}`, 'chat')

ws.onopen = t.fail

ws.addEventListener('error', ({ error }) => {
t.ok(error)
})
})

t.teardown(server.close.bind(server))
})

0 comments on commit 19a758a

Please sign in to comment.