-
Notifications
You must be signed in to change notification settings - Fork 2
/
http2ws.js
executable file
·77 lines (66 loc) · 2.29 KB
/
http2ws.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
'use strict'
const http2 = require('http2')
const websocket = require('websocket-stream')
const WebSocket = require('ws')
const settings = { enableConnectProtocol: true }
const server = http2.createServer({ settings })
function createWebSocket(stream, headers) {
// Take the Http2Stream object and set it as the "socket" on a new
// ws module WebSocket object.. then wrap that using the websocket-stream...
// It's not quite a perfect fit yet... but we have to start somewhere to
// prove it works.
stream.setNoDelay = function() {} // fake it for now...
const ws = new WebSocket(null)
ws.setSocket(stream, headers, 100 * 1024 * 1024)
return websocket(ws)
}
server.on('stream', (stream, headers) => {
if (headers[':method'] === 'CONNECT') {
stream.respond({
'sec-websocket-protocol': headers['sec-websocket-protocol']
})
const ws = createWebSocket(stream, headers)
ws.pipe(ws) // echo echo echo...
} else {
// If it's any other method, just respond with 200 and "ok"
stream.respond()
stream.end('ok\n')
}
})
server.listen(0, () => {
const origin = `http://localhost:${server.address().port}`
const client = http2.connect(origin)
// Let's throw other simultaneous requests on the same connection, for fun!
function ping() {
client.request().pipe(process.stdout)
}
setInterval(ping, 2000)
// Setup the WebSocket over HTTP/2 tunnel... per RFC 8441, we cannot attempt
// to do this until after we receive a SETTINGS frame that enables use of
// the extended CONNECT protocol...
client.on('remoteSettings', (settings) => {
if (!settings.enableConnectProtocol)
throw new Error('whoops! something went wrong!')
const req = client.request({
':method': 'CONNECT',
':protocol': 'websocket',
':path': '/chat',
'sec-websocket-protocol': 'chat',
'sec-websocket-version': 13,
origin
})
// As soon as we get a response, we can set up the client side of the
// WebSocket....
req.on('response', (headers) => {
// We really ought to be checking the status code first...
const ws = createWebSocket(req, headers)
ws.setEncoding('utf8')
ws.on('data', console.log)
process.stdin.pipe(ws)
})
req.on('close', () => {
server.close()
client.close()
})
})
})