Repository navigation
Conversation
469125f to
9470379
Compare
0616f05 to
047d1c0
Compare
code-asher
left a comment
There was a problem hiding this comment.
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.
Amazing skills 👍 👍
Have you tried to establish a connection using other tools? JS possibly?
|
|
||
| // 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.
This model will work until one day we will need to switch to HTTP3.99 :)
| }); ok { | ||
| ginWriter.WriteHeaderNow() | ||
| switch opts.Protocol { | ||
| case ProtocolHTTP2: |
There was a problem hiding this comment.
Should we support http.UnencryptedHTTP2?
There was a problem hiding this comment.
I did not know about this, I'll need to investigate. Thanks for the heads up 👍🏻
There was a problem hiding this comment.
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: |
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
ea8732a to
00fa373
Compare
Add resp.ProtoMajor check in verifyServerResponseH1 for consistency with verifyServerResponseH2 which already performs this check. Refs #539
| switch proto { | ||
| case HTTPProtocol2: | ||
| // Prepare response headers for H2 (no Connection/Upgrade). | ||
| w.Header().Set("Sec-WebSocket-Accept", secWebSocketAccept(key)) |
There was a problem hiding this comment.
sec-websocket-key and sec-websocket-accept are not part of WebSocket HTTP/2 as per RFC 8441
|
Are there plans to ship this? |
|
@Nek-12 yes, absolutely! This fell on the back-burner but I will take another look at it next week. |
|
@mafredri With go 1.27 x/net/http2 moved into the standard library. It might be worth to relook into the changes. See: https://pkg.go.dev/golang.org/x/net/http2#section-readme I would be interested in the http2 websocket server. Do you need any help to ship this? |
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
Nothing calls ci/static.sh, and it reads ci/out/profile.txt, which ci/test.sh does not write (it writes ci/out/coverage.prof). The script only works with the ci/test.sh changes in #539, so it moves back there and this PR only drops the dev branch jobs.
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
- 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
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.
Add resp.ProtoMajor check in verifyServerResponseH1 for consistency with verifyServerResponseH2 which already performs this check. Refs #539
3f2f9af to
fd5e7f7
Compare
verifyServerResponseH1 rejects responses whose ProtoMajor is not 1. These mock responses left it at 0, so each dial failed before the check its test targets. Responses from net/http always set ProtoMajor.
Without the check, an HTTP/3 response goes on to the Upgrade header checks, so Dial could treat it as an HTTP/1.1 upgrade.
http2.Transport.DialTLS is deprecated, and staticcheck fails lint on it. DialTLSContext also lets the transport cancel a dial when the request's context ends.
http2.Transport.DialTLS is deprecated, and staticcheck fails lint on it.
Custom RoundTrippers that build the 101 response by hand may leave ProtoMajor at 0. Rejecting those would break dials that work today, while any other version except 1 is still rejected.
This reverts 3866540. With an unset ProtoMajor accepted, these tests again cover the hand-built responses that custom RoundTrippers return.
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.