-
Notifications
You must be signed in to change notification settings - Fork 335
feat: add experimental http2 support #539
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
469125f to
9470379
Compare
0616f05 to
047d1c0
Compare
code-asher
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice 🤌 I messed around with the example as well and it all looks good.
mtojek
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing skills 👍 👍
Have you tried to establish a connection using other tools? JS possibly?
protocol.go
Outdated
|
|
||
| // ProtocolHTTP1 selects HTTP/1.1 GET+Upgrade for the WebSocket handshake. | ||
| // This is the default (zero value). | ||
| ProtocolHTTP1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This model will work until one day we will need to switch to HTTP3.99 :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ProtocolHTTP3_99 😂
accept.go
Outdated
| }); ok { | ||
| ginWriter.WriteHeaderNow() | ||
| switch opts.Protocol { | ||
| case ProtocolHTTP2: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we support http.UnencryptedHTTP2?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not know about this, I'll need to investigate. Thanks for the heads up 👍🏻
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked into this. Server-side already works with native h2c since the code checks r.ProtoMajor == 2, which handles both approaches the same way. The GODEBUG=http2xconnect=1 env is still needed though.
Client-side is the main issue. I tested Go 1.25, and the native http.Transport still rejects the :protocol pseudo-header, so the http2.Transport from x/net is needed.
Looks like full stdlib support is targeted for Go 1.26 (golang/go#67810), we can revisit then.
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 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: |
- Fix 'exampels' typo in CI workflow comments - Fix README paths to use 'internal/examples/http2' - Change visibleAddr to display 0.0.0.0 for all-interface bindings
Remove bench-dev and test-dev jobs from daily workflow since the dev branch no longer exists. Add ci/static.sh script to generate coverage badge for GitHub Pages. Refs #539
Add resp.ProtoMajor check in verifyServerResponseH1 for consistency with verifyServerResponseH2 which already performs this check. Refs #539
Rename the Protocol type to HTTPProtocol for consistency with existing HTTPClient and HTTPHeader field naming in DialOptions. Constants are also renamed: - ProtocolHTTP1 → HTTPProtocol1 - ProtocolHTTP2 → HTTPProtocol2 - ProtocolAcceptAny → HTTPProtocolAny
Simplify the TLS example by requiring -cert and -key flags instead of auto-generating a self-signed certificate. This reduces complexity and keeps the example focused on HTTP/2 WebSocket usage.
ea8732a to
00fa373
Compare
This change adds experimental support for WebSockets over HTTP/2 (RFC 8441).
Implementation notes:
internal/thirdparty/http2(they require importinggolang.org/x/net/http2, see net/http: move HTTP/2 into std golang/go#67810)GODEBUG, see net/http: add support for SETTINGS_ENABLE_CONNECT_PROTOCOL golang/go#53208Dialbecause we cannot test the underlying transport for support (for instance,http.Transportdoes not allow setting the HTTP/2 pseudo-header:protocol)Dialwith HTTP/2 support, ahttp2.Transportmust be provided viaDialOptions.Client(since we do not importgolang.org/x/net/http2)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.