You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Reacted by Nia, Paul Tötterman, Tai, MarcyMarcy, Youfu Zhang, Bradley Wilson-Hunt, Fabian Weisshaar, Viacheslav Vasilyev, Thanatat Tamtan, Roman Sharkov and 16 more
Hi, I have been building a similar websocket package, and would be willing to help if I can. Some things I can share:
I also looked into the problem of identifying whether an endpoint supports HTTP/2 WebSockets. The best I came up with was similar to that suggested elsewhere - use an HTTP/2 connection first, then downgrade to HTTP/1 if necessary. However, SETTINGS_ENABLE_CONNECT_PROTOCOL, and similar host-wide mechanisms are not actually sufficient to identify whether an endpoint supports RFC8441 or not - I think it can be theoretically confused by a non-RFC8441 service behind an RFC8441-compliant reverse proxy. In reality, once this gets pushed out into the world a lot of services are likely to have partial support during an upgrade period - with some endpoints using the upgraded websocket packages and others not yet supporting it. The most foolproof way I came up with is to send a request and check for a 405 Method Not Allowed status code. Any RFC6455-compliant server will return a 405 Method Not Allowed if it recieves an unrecognized method, such as CONNECT as used here. When I checked, all implementations I found did this correctly.
The rw body for successful HTTP/2 Connect requests has already been implemented. I have tested it out, and it works.
I did open an issue which you linked about being able to set the :protocol header. I have been looking into that, and so far I have not come up with any reasonable way to expose this behavior beyond adding an override hack like the one currently used to force HTTP/1 for websockets.
I see you on some of the related threads, so some of this is just to provide context to anyone else reading this issue thread.
Reacted by Adam Quinn Snow, AuroraTea and tony loc
The rw body for successful HTTP/2 Connect requests has already been implemented. I have tested it out, and it works.
Nice.
However, SETTINGS_ENABLE_CONNECT_PROTOCOL, and similar host-wide mechanisms are not actually sufficient to identify whether an endpoint supports RFC8441 or not - I think it can be theoretically confused by a non-RFC8441 service behind an RFC8441-compliant reverse proxy.
I think it should be fine. A RFC 8441-complaint reverse proxy would translate HTTP/2 over web sockets into HTTP/1.1 for the origin server. e.g. Nginx translates all HTTP/2 requests into HTTP/1.1 for origin servers. Otherwise it wouldn't be RFC 8441-complaint if it just proxied the request directly.
I did open an issue which you linked about being able to set the :protocol header. I have been looking into that, and so far I have not come up with any reasonable way to expose this behavior beyond adding an override hack like the one currently used to force HTTP/1 for websockets.
Yea that is unfortunate. Maybe a new field on *http.Request to set custom pseudo headers forcing HTTP/2? Or translating the HTTP/1.1 Protocol header to :protocol for HTTP/2? I think that would be reasonable.
Hi, I have been building a similar websocket package, and would be willing to help if I can.
See my proposal at golang/go#32763 (comment) to make net/http transparently handle http/2 upgrades server side and client side.
Would be much nicer than implementing it here as all Go WebSocket server's would work over HTTP/2 and we would get client side support for free as we use net/http's Client directly.
Reacted by Doug Richardson, Hannes, Boris Smidt and Vinicius Fortuna
@hons82 Unfortunately apart from forking the go net/http library nope. I don't think it'd be very difficult to implement but there just hasn't been a response from the Go team on the linked issue.
Reacted by Martin Benda, Andrei Surugiu, Weibin, Felix Sandelin, Kasper Damgård, Pascal FILIPOVICZ, AuroraTea, Zxilly, Márk Bartos, Nuno Rodrigues and 17 more
I'm full time on websocket the next few months. There hasn't been any movement on the Go issue but I think I'll just fork net/http and implement my proposal linked above there. Then people can use my fork if they want WebSockets over http/2 with my library.
As well I'll open a CL on the standard library with my proposal so hopefully my fork won't be necessary. These things don't tend to get moving on issue trackers unless someone shows the initiative by implementing and demonstrating the demand.
Reacted by Arran Ubels, Youfu Zhang, Daniel Sokil, tony loc, F.Baube and Hannes
@XpamAmAdEuS we have been following the development and this is something we're looking to implement. It's now at a stage where implementing it makes sense for us, however, no work has started on this yet, so contributions are also welcome. Hoping this will be moved out of GODEBUG and be made part of the API in the future 🤞🏻.
http2xconnect just controls the default. A library like this can enable HTTP2 connect support without having to resort to GODEBUG, but the reason is that it is only reasonable to do so if you then really have somebody to handle connect requests (like this library can then do it).
I'm currently working on an implementation for this (which will require enabling GODEBUG=http2xconnect=1 for the time being).
I'd like to hear what you think about what kind of API coder/websocket should expose for HTTP/2 support? I'm thinking question like:
Should there be no API changes, just handle HTTP/2 transparently?
Should HTTP/2 support be manually enabled?
Should Accept accept either HTTP/2 or HTTP/1, or should it accept both if HTTP/2 support is enabled?
Should Dial work transparently with either HTTP/1 and HTTP/2?
Should we provide a http2 package to help with options/transports? Ideally this won't be needed if golang.org/x/net/http2 is ever promoted to stdlib.
These are just questions, and are not necessarily feasible with the current state of HTTP/2 in Go. I am, however, interested in your thoughts. I'd be especially grateful for feedback from users who have dealt with HTTP/2 before.
One ideal/goal is to keep coder/websocket dependency free, which means not importing golang.org/x/net/http2. What this means for example in Dial is that you're required to enable HTTP/2 via options and to provide a http.Client with a http2.Transport set. Go has the concept of upgrading a net/http Transport to attempt HTTP/2 or fallback to HTTP/1, but it does not allow setting the HTTP/2 :protocol header. That breaks RFC 8441 and is why providing a http2.Transport manually becomes a necessity.
Activity
nhooyr commentedon Jul 15, 2019
Related:
nhooyr commentedon Jul 15, 2019
Could probably implement this reasonably quickly if we forked x/net/http2.
:protocolpseduo header.niaow commentedon Jul 16, 2019
Hi, I have been building a similar websocket package, and would be willing to help if I can. Some things I can share:
SETTINGS_ENABLE_CONNECT_PROTOCOL, and similar host-wide mechanisms are not actually sufficient to identify whether an endpoint supports RFC8441 or not - I think it can be theoretically confused by a non-RFC8441 service behind an RFC8441-compliant reverse proxy. In reality, once this gets pushed out into the world a lot of services are likely to have partial support during an upgrade period - with some endpoints using the upgraded websocket packages and others not yet supporting it. The most foolproof way I came up with is to send a request and check for a 405 Method Not Allowed status code. Any RFC6455-compliant server will return a 405 Method Not Allowed if it recieves an unrecognized method, such asCONNECTas used here. When I checked, all implementations I found did this correctly.rw body for successful HTTP/2 Connect requestshas already been implemented. I have tested it out, and it works.:protocolheader. I have been looking into that, and so far I have not come up with any reasonable way to expose this behavior beyond adding an override hack like the one currently used to force HTTP/1 for websockets.I see you on some of the related threads, so some of this is just to provide context to anyone else reading this issue thread.
nhooyr commentedon Jul 16, 2019
Nice.
I think it should be fine. A RFC 8441-complaint reverse proxy would translate HTTP/2 over web sockets into HTTP/1.1 for the origin server. e.g. Nginx translates all HTTP/2 requests into HTTP/1.1 for origin servers. Otherwise it wouldn't be RFC 8441-complaint if it just proxied the request directly.
Yea that is unfortunate. Maybe a new field on
*http.Requestto set custom pseudo headers forcing HTTP/2? Or translating the HTTP/1.1 Protocol header to:protocolfor HTTP/2? I think that would be reasonable.Awesome, would love your help :)
So then the remaining items here are:
nhooyr commentedon Nov 5, 2019
See my proposal at golang/go#32763 (comment) to make net/http transparently handle http/2 upgrades server side and client side.
Would be much nicer than implementing it here as all Go WebSocket server's would work over HTTP/2 and we would get client side support for free as we use net/http's Client directly.
hons82 commentedon May 13, 2021
Hi... is there a workaround that can be used until go supports something in that direction?
nhooyr commentedon Aug 6, 2021
@hons82 Unfortunately apart from forking the go net/http library nope. I don't think it'd be very difficult to implement but there just hasn't been a response from the Go team on the linked issue.
prologic commentedon Apr 6, 2022
@nhooyr Any further updates or progress on this?
nhooyr commentedon Aug 16, 2023
I'm full time on websocket the next few months. There hasn't been any movement on the Go issue but I think I'll just fork net/http and implement my proposal linked above there. Then people can use my fork if they want WebSockets over http/2 with my library.
As well I'll open a CL on the standard library with my proposal so hopefully my fork won't be necessary. These things don't tend to get moving on issue trackers unless someone shows the initiative by implementing and demonstrating the demand.
tv42 commentedon Aug 16, 2023
I believe the link was meant to be #402
mitar commentedon Oct 21, 2023
Have you seen golang/go#49918?
mitar commentedon Oct 21, 2023
Also golang/go#53209 and golang/go#53208.
nhooyr commentedon Oct 22, 2023
Nope, I missed those thanks for the links!
hons82 commentedon Oct 23, 2023
That would be awesome
fbaube commentedon Nov 13, 2023
XpamAmAdEuS commentedon Feb 12, 2025
go 1.24 is released and we can enable http2 connect with GODEBUG=http2xconnect=1
mafredri commentedon Feb 12, 2025
@XpamAmAdEuS we have been following the development and this is something we're looking to implement. It's now at a stage where implementing it makes sense for us, however, no work has started on this yet, so contributions are also welcome. Hoping this will be moved out of
GODEBUGand be made part of the API in the future 🤞🏻.mitar commentedon Feb 12, 2025
http2xconnectjust controls the default. A library like this can enable HTTP2 connect support without having to resort to GODEBUG, but the reason is that it is only reasonable to do so if you then really have somebody to handle connect requests (like this library can then do it).mafredri commentedon Feb 12, 2025
@mitar I believe that's still in proposal phase (golang/go#53208 (comment))?
mitar commentedon Feb 12, 2025
It seems you are right! Thanks.
But it also seems this will require only golang.org/x/net bump and not a new Go release, and golang.org/x/net is released monthly.
mafredri commentedon Sep 15, 2025
I'm currently working on an implementation for this (which will require enabling
GODEBUG=http2xconnect=1for the time being).I'd like to hear what you think about what kind of API
coder/websocketshould expose for HTTP/2 support? I'm thinking question like:Acceptaccept either HTTP/2 or HTTP/1, or should it accept both if HTTP/2 support is enabled?Dialwork transparently with either HTTP/1 and HTTP/2?http2package to help with options/transports? Ideally this won't be needed ifgolang.org/x/net/http2is ever promoted to stdlib.These are just questions, and are not necessarily feasible with the current state of HTTP/2 in Go. I am, however, interested in your thoughts. I'd be especially grateful for feedback from users who have dealt with HTTP/2 before.
One ideal/goal is to keep
coder/websocketdependency free, which means not importinggolang.org/x/net/http2. What this means for example inDialis that you're required to enable HTTP/2 via options and to provide ahttp.Clientwith ahttp2.Transportset. Go has the concept of upgrading anet/httpTransport to attempt HTTP/2 or fallback to HTTP/1, but it does not allow setting the HTTP/2:protocolheader. That breaks RFC 8441 and is why providing ahttp2.Transportmanually becomes a necessity.mitar commentedon Sep 15, 2025
I think that importing golang.org/x/net/http2 is pretty safe and I would not call it really a dependency. :-)
feat: add experimental http2 support
feat: add experimental http2 support
feat: add experimental http2 support
feat: add experimental http2 support
feat: add experimental http2 support
feat: add experimental http2 support
feat: add experimental http2 support
feat: add experimental http2 support
feat: add experimental http2 support
feat: add experimental http2 support
feat: add experimental http2 support
feat: add experimental http2 support
fix(ingress): migrate WebSocket proxy off archived gorilla/websocket
feat: add experimental http2 support
feat: add experimental http2 support