websocket
websocket copied to clipboard
feat: add experimental http2 support
This change adds experimental support for WebSockets over HTTP/2 (RFC 8441).
Implementation notes:
- To avoid breaking any flows, HTTP/2 functionality is currently opt-in on both server and client
- The HTTP/2 tests are currently kept in
internal/thirdparty/http2(they require importinggolang.org/x/net/http2, see https://github.com/golang/go/issues/67810) - HTTP/2 extended CONNECT must currently be enabled via
GODEBUG, see https://github.com/golang/go/issues/53208 - Explicit selection of HTTP/1 or HTTP/2 is required during
Dialbecause we cannot test the underlying transport for support (for instance,http.Transportdoes not allow setting the HTTP/2 pseudo-header:protocol) - To
Dialwith HTTP/2 support, ahttp2.Transportmust be provided viaDialOptions.Client(since we do not importgolang.org/x/net/http2) - There are a few changes and cleanups unrelated to this feature, if needed they can be broken out into a separate branch
Closes #4
This change does not yet include benchmark tests for HTTP/2, those will be added at a later date as a follow-up.
Have you tried to establish a connection using other tools? JS possibly?
While I was testing I experimented with connecting to the server example from a JS (Node) client. Here is what I used for anyone interested (needs ws).
const http2 = require("http2")
const { Receiver, Sender } = require("ws")
const client = http2.connect("http://127.0.0.1:8080")
const req = client.request({
":method": "CONNECT",
":protocol": "websocket",
":scheme": "http",
":path": "/",
":authority": "127.0.0.1",
"Sec-WebSocket-Key": "AQIDBAUGBwgJCgsMDQ4PEC==",
"Sec-WebSocket-Version": "13",
})
req.on("response", (headers) => {
console.log("status:", headers[":status"])
})
req.on("error", (err) => {
console.log("error:", err)
})
const receiver = new Receiver()
receiver.on("message", (data) => {
console.log("got message:", data.toString())
})
req.on("data", (chunk) => {
receiver.write(chunk)
})
setInterval(() => {
const sender = new Sender(req)
sender.send("hey", { binary: false, mask: true, fin: true })
}, 1000)
sample output:
status: 200
got message: hey
got message: hey
got message: hey