golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.61k stars 17.61k forks source link

net/http: support HTTP/3 #32204

Open johanbrandhorst opened 5 years ago

johanbrandhorst commented 5 years ago

I searched for an issue to track progress of implementing HTTP/3 in the standard library but couldn't find one, so I'm opening this new issue to track this (presumably inevitable) effort.

HTTP/3 is still an IETF draft, so there's not too much point starting work on this yet. The relevant spec is (currently) available here: https://quicwg.org/base-drafts/draft-ietf-quic-http.html.

Some questions we may want to answer before any work starts:

  1. Should work on this start in one of the x repos, like HTTP/2 did?
  2. What if any existing libraries can be used as a base for the new HTTP/3 work?

Of note is an existing attempt at implementing QUIC and HTTP/3 in pure go: https://github.com/lucas-clemente/quic-go.

dsymonds commented 5 years ago

Cloudflare now supports HTTP/3, and Chrome and Firefox will shortly start supporting it: https://blog.cloudflare.com/http3-the-past-present-and-future/

rajveermalviya commented 4 years ago

Not to say we're in a race, but node has started implementing quic protocol in a draft PR.

Reference

Now, some bad opinions (if the go team is accepting them):

trivikr commented 4 years ago

but node has started implementing quic protocol in a draft PR.

Correction: The Node.js QUIC implementation began back in Q1 2019, the draft PR is the result of all that work https://github.com/nodejs/node/issues/23064

vyrwu commented 4 years ago

Is there any progress on this? There are some existing open-source libs like quic-go that can be used for experimenting with quic, but it would be really neat to have something experimental from the std go lib.

hekmon commented 4 years ago

:rocket: https://blog.chromium.org/2020/10/chrome-is-deploying-http3-and-ietf-quic.html

hherman1 commented 4 years ago

Has there been any word from leadership on whether or not this will be supported?

ianlancetaylor commented 4 years ago

I'm not sure which leadership you are asking about.

I think it's clear that Go must support HTTP/3. This issue is a good place to record the work that needs to be done. But it is one thing to say "we must do this" and it is a very different thing to say "this is how it will be done."

hherman1 commented 3 years ago

Sorry I’m not sure how that came off, I was just wondering if there was any official word on if this will be supported. Couldn’t find any on the issue tracker. Thanks for the quick answer though!

sylr commented 3 years ago

It seems to me that it is still a long way from now to we must do this.

I might have missed it but so far I did not see any interest shown in this subject from any of the net & net/http usual committers. Also a research about HTTP/3 or QUIC in golang-dev does not seem to yield any significant results.

It would be nice to see a discussion started amongst people actually capable of bringing it into the standard library.

makew0rld commented 3 years ago

Golang might be behind the times for this feature.

It's worth noting that HTTP/3 is not finalized by the IETF at this point. It is not enabled by default in Firefox and has experimental support. Google likes to push this protocol forward a lot and is using it already in Chrome, but it is still experimental and not finalized. I understand the Go team hesitating to start supporting a protocol that isn't even complete yet.

mholt commented 3 years ago

Hmm, well, Go's standard library has never been one to quickly adopt new technologies -- not without a lot of scrutiny. HTTP/2 might possibly be the exception, but even it was not vendored in from an external package until well after the spec was standardized. HTTP/3 isn't finished being standardized yet.

HTTP/3 is more complex than HTTP/2, and there's a lot of code necessary to make it work. I've been using and deploying lucas-clemente/quic-go for a couple years now (in Caddy, so we're already seeing a lot of experimental production deployments) -- frankly it's a beast. What's the benefit of having it in the standard library right now?

It's OK if it's not in the standard library right away. I'd rather the standard implementation be correct, elegant, and stable, true to the reputation of the Go standard library.

ShivanshVij commented 3 years ago

I understand what you’re saying, but the issue is that the NodeJS team had been experimenting with Quic support for months before this release.

Now that companies like Cloudflare and Google are beginning support, it’s unlikely that the IETF standard will change drastically.

There’s no reason not to begin implementation or at least experimentation and make whatever small tweaks are necessary for the general availability release once the standard is completed by IETF.

ShivanshVij commented 3 years ago

@mholt is completely correct in saying that whatever finalized HTTP/3 library is released should be elegant and stable. However, what I am saying is that I believe that we should at least begin an in-depth discussion on the topic instead of just saying we will wait for the standard to be completed by IETF.

If we leave it until later, then I can see an issue where people will want to use the vast benefits of HTTP/3 but be unable to do so with Golang. (This is the main reason I have to write my server code in NodeJS right now, HTTP/3 is a requirement for us)

makew0rld commented 3 years ago

Google has been using and pushing HTTP/3 since before it was even called that, they deployed their super-experimental non-standardized original version of the protocol in Chrome as early as 2012. It is not surprising they are still using and pushing it now, while it is still not standardized. I would argue Cloudflare is also supporting it prematurely, likely to test their implementation at scale.

No browser currently supports HTTP/3 by default. See https://caniuse.com/http3

image

However, what I am saying is that I believe that we should at least begin an in-depth discussion on the topic instead of just saying we will wait for the standard to be completed by IETF.

I agree that beginning discussion would be helpful. I'm just saying I understand why it hasn't happened yet, and I think there is still plenty of time. The current usage and demand for HTTP/3 seems to be effectively zero.

This is the main reason I have to write my server code in NodeJS right now, HTTP/3 is a requirement for us

Why not use quic-go?

pofl commented 3 years ago

As I see it, QUIC and HTTP/3 are so far into the IETF process that they are hardly bound to change anymore, definitely not substantially. Let me argue that if somebody would start implementing now they will not have to throw away any part of the implementation due to changes to the standard. By lying in wait for the finalization Go is only perpetuating the chicken-and-egg problem.

Not that any of this is a problem. Just my two cents.

FireMasterK commented 3 years ago

Has there been any progress on bringing an official implementation? Is there any issue that is blocking this?

I can't seem to understand what's blocking this, there seems to be a lot of interest too. Sure, quic-go does the job, but I'm sure it's nice to have official support for quic.

awnumar commented 3 years ago

Overview of HTTP/3 support amongst clients and servers: https://daniel.haxx.se/blog/2021/04/02/where-is-http-3-right-now/

tldr: the level of HTTP/3 support in servers are surprisingly high considering very few clients enable it by default yet.

I assume that the rest of the browsers will also enable HTTP/3 by default soon, and the specs will be released not too long into the future. That will make HTTP/3 traffic on the web increase significantly.

The TLS library situation will continue to hamper wider adoption among non-browsers and smaller players.

awnumar commented 3 years ago

A few more browsers support it now: https://caniuse.com/http3

image

nirui commented 3 years ago

Guys, guys, something to read about:

schoenenberg commented 3 years ago

QUIC has been published by the IETF as RFC 9000!

See this post: QUIC is now RFC 9000

HN Discussion: https://news.ycombinator.com/item?id=27310349

DeedleFake commented 3 years ago

Note that that does not include HTTP/3. That'll be a separate RFC later on. I do think that this shows that it's about time to get an official QUIC implementation, though, either directly in net or in something like net/quic. If it starts in golang.org/x/net/quic first, that's fine, too.

seankhliao commented 3 years ago

Quic is #44886

aojea commented 3 years ago

I think it's clear that Go must support HTTP/3

@ianlancetaylor is it fair to assume that in a future if I do:

resp, err := http.Get("https://example.com/")

can I be using UDP underneath?

The context is about code that use the golang net/http library to implement HTTP/s probes, my understanding is that golang will probably end defaulting to http3, as it happened with http2, so, it will not be safe to assume http == TCP using net/http

ianlancetaylor commented 3 years ago

@aojea I don't know anything about the code you mention, so I don't know whether it matters, but, yes, I agree that in the future it will not be safe to assume that the net/http package uses TCP underneath.

alexec commented 2 years ago

Yes please to this! Very exciting!

karelbilek commented 2 years ago

Hello.

Sorry if I am being annoying. Is Go team planning to implement http3 (and therefore quic) client/server in go library and is there some sort of timeline?

Or is go team first waiting for the draft to be finalized? Currently, there is already support in browsers (including Google's own Chrome) based on that draft.

Thanks.

CNTWDev commented 2 years ago

Hello.

Sorry if I am being annoying. Is Go team planning to implement http3 (and therefore quic) client/server in go library and is there some sort of timeline?

Or is go team first waiting for the draft to be finalized? Currently, there is already support in browsers (including Google's own Chrome) based on that draft.

Thanks.

is there any progress?

awnumar commented 2 years ago

is there any progress?

These useless comments ping everyone who is subscribed to this thread. Stop with the spam

lemon-mint commented 2 years ago

Now HTTP/3 is standardized

https://www.rfc-editor.org/rfc/rfc9114.html

thomasf commented 2 years ago

That document has the "Proposed standard" state and not "Internet Standard" but it is on the more stable side of the standardization process now.

mnordhoff commented 2 years ago

For that matter, HTTP/2 is also a Proposed Standard.

DeedleFake commented 1 year ago

Judging by the number of references to this issue above, it seems there are quite a few projects waiting on this for various things. I'm personally just as interested in raw QUIC support as I am HTTP/3. Any chance of it happening? It's been pretty quiet for a while despite both protocols getting standardized.

DeedleFake commented 1 year ago

Should this issue have a proposal label? There was a proposal that was closed as a duplicate of this issue, but this one isn't labeled as one and I worry that the proposal review team may be overlooking it because of that.

ianlancetaylor commented 1 year ago

I don't think it would be helpful to send this issue through the proposal committee at this point. The proposal committee is useful for coming to agreement on new API or precisely defined new functionality. But so far nobody has described an API or exactly what it means to support HTTP/3 (I don't know myself).

In particular the proposal committee can't cause anybody to actually work on this. That seems like the most useful next step here.

mholt commented 1 year ago

@marten-seemann Want to work together on a proposal for HTTP/3 in the Go standard library?

jefer94 commented 1 year ago

@ianlancetaylor I supposed with "support HTTP/3" they refer to start to implement this draft https://datatracker.ietf.org/doc/html/rfc9114 inside the net package of Go, exists one team have a implementation of QUIC https://github.com/lucas-clemente/quic-go this can be the start point to do the first implementation of HTTP/3, also part of this draft was wrote by the team of QUIC, this team is belong to Google, using set theory you can determine the difference between both protocols and do the parts is not in the intersection, that should be useful to continue with the rest of steps

jefer94 commented 1 year ago

Here appear a implementation in other programming languages https://en.wikipedia.org/wiki/HTTP/3 they says have HTTP/3 implemented, if it is true you can copy/paste that code and convert it to Go

mholt commented 1 year ago

Marten and I have already exchanged some emails on the topic. Go's standard lib would have to implement the QUIC protocol which, unfortunately, has a lot of knobs and callbacks that are needed for secure and efficient deployments. My current understanding is that adding QUIC to the standard library would export considerable API surface area, including on the crypto/tls package, which is probably not desirable. (Maybe some of it could be refactored into an internal package, but still -- not trivial.) To minimize the exported API we'd need to have smart or sane defaults, but it's not clear to me, at least, what those defaults should be in the general case.

The most minimal QUIC implementation would lose a number of security and performance enhancements. Some examples include address verification (which should be done when the server is "under load" -- but only certain kinds of load -- to prevent amplification attacks) advertising HTTP/3 in the Alt-Svc header (which requires knowing the external port number), 0-RTT, WebTransport API, among others.

I suppose a good, minimal starting point for the API would be to have a function like http.ListenAndServeTLS() start a listener on a UDP socket as well as it does for a TCP socket.

For methods like http.Server.Serve(ln, handler), things are a little trickier since you'd have to have a net.Listener as well as a net.PacketConn for the UDP socket. Maybe the standard library could assume the same port as the given listener (if a TCP listener) and start its own UDP listener? But that does feel a bit "magical" for the standard library. (If it was an external library, I'd be more OK with that. But I don't feel right doing that in the standard lib.)

Anyway, many questions remain to be answered in the proposal drafting process.

james-lawrence commented 1 year ago

@mholt I think the questions you should be asking is what kind of surface API would the stdlib need to expose to support QUIC implementations in a composable manner with other transports. there is already a quic implemention for golang in the wild; but it didn't really try to be very composable with other transport APIs in the stdlib. but it has brought improvements to the TLS api just by existing.

focusing on http in particular isn't a great approach as there are far more uses for quic than http. I think the main thing stdlib is missing is a concept of a multiplex transport that has both packet and reliable transport behaviors.

Ideally we wouldn't need to expand on HTTP's api at all if we get the lower level transport API done correctly. we'd just be able to pass the quic.Listener to the http server just like we do now for tcp and unix listeners.

the port question seems misguided; just call http.Serve twice http.Serve(quic, handler) http.Serve(tcp, handler) or write a composite transport listener. if the programmer is using the ":#" method on http then the reasonable assumptions (assume same port) are perfectly fine as they are opting into them.

komuw commented 1 year ago

Related: https://github.com/golang/go/issues/58547 : proposal: x/net/quic: add QUIC implementation

codewinch commented 1 year ago

According to https://caniuse.com/http3 and if I'm reading the chart right, over 70% of clients globally now support HTTP/3, with the main holdouts being Apple Safari. As far as I know, Go doesn't even have an official server in any kind of testing; it's especially strange given that Google was a very strong driver behind the global HTTP/3 adoption.

kgersen commented 1 year ago

As a user I'm a bit concerned about how the Go team is handling QUIC and HTTP/3.

It now seems they had no plan up to a few days ago with that x/net/quic proposal (which is just the definition of an API not an actual implementation).

May be we misunderstood but, like a lot of people, we thought quic-go was some kind of official "Google sponsored" effort to add QUIC & HTTP/3 to Go since Lucas Clemente is a Googler... it seems we were wrong as there are clearly no sign of collaboration between them. That one is on us, we should have ask.

But that is concerning in term of timing for an official support of HTTP/3 in Go. We're a couple years late here...and does this implies that quic-go is wasted effort or not worth reusing?

A big reason people are choosing Go is the famous 'batteries included' feature particularly net/http. If Go starts lagging in that area ,less & less people will use it for new projects. Not treating the evolutions of net/http at a higher priority seems, to me, a mistake.

That been said if the Go team ever add HTTP/3 to std lib, it would be nice to avoid some of the "ugly tricks" they used when they added HTTP/2, mainly the 'h2_bundle.go' trick and that awful hardcoded exception in crypto/tls among others...

codewinch commented 1 year ago

To be fair, it's not just Go. To a large extent, it's also a reliance on a proper TLS library, since OpenSSL has basically destroyed itself.

For example, this HA Proxy thread has a great explanation of the issues surrounding TLS libs that have QUIC support:

https://github.com/haproxy/haproxy/issues/680

Akamai and NGINX are in the same difficult position of trying to work with a recalcitrant and insecure OpenSSL that doesn't want to move forward, and Linux distributions need to really step up quickly as well.

Perhaps the best option for the Go community as well as everyone else is to move forward with the Rust library WolfSSL, which seems to be a lot safer than OpenSSL (and more stable than Google's own BoringSSL.)

It might seem to be anathema to suggest using a Rust library like WolfSSL in Go, but if it's the best solution then it would let us move forward to H3 fastest, and if all of the other web and server vendors standardize on it, then it'd help get a valid, reliable, fast, and most of all secure solution into the distros that much faster.

karelbilek commented 1 year ago

@codewinch isn't go's using BoringCrypto anyway for the crypto primitives, and native Go code for the rest of the SSL logic?

I don't understand how is OpenSSL relevant here at all

edit: ah the boringcrypto is behind GOEXPERIMENT=boringcrypto. I did not know that. so Go doesn't use any C crypto library by default

DeedleFake commented 1 year ago

It might seem to be anathema to suggest using a Rust library like WolfSSL in Go

I don't mind that it's Rust (In fact, I think Rust support in cgo would be neat.), but using it would break anything using SSL with CGO_ENABLED=0. If at all possible, the standard library should implement the necessary pieces itself as part of the existing pure Go SSL package that's aready in there.

ShivanshVij commented 1 year ago

Personally I’d love to use wasm for this - compiling rust to wasm is usually pretty painless, and the wazero project allows you to run wasm code without CGO.

Plus, we’ve already seen demos where go farms out to a rust wasm binary to do regex (https://github.com/loopholelabs/scale-benchmarks) and the perf using wazero is pretty good. (@codefromthecrypt)

With all that being said however, I don’t think the biggest issue is what kind of SSL lib we should use (or how) - it’s trying to find the fastest way to add HTTP/3 support (ie. with the least amount of work).

Being able to use rust via CGO is definitely cool (and I’d love to see it too!) but the go team would have to first add that feature, then integrate a foreign SSL library, and then (and only then) could they start work on the HTTP/3 implementation.

Frankly the easiest path forward would be to take the existing quic-go implementation and just integrate it into the stdlib.

Obviously you’d need to rewrite parts of it but if it already works, why throw it away?

DeedleFake commented 1 year ago

the wazero project allows you to run wasm code without CGO

The issue isn't running it but rather compilation. This change would require a Rust compiler on the system in order to build the Go standard library, and especially with the new changes in 1.20 to not ship a pre-compiled standard library with distributions of Go, this seems like a rather huge change and potential major problem for many, many people downstream.

Frankly the easiest path forward would be to take the existing quic-go implementation and just integrate it into the stdlib.

I agree, that seems like the best option to me, too. I'd like some API cleanups and whatnot, plus better integration with, say, net.Dial() possible, but the implementation itself clearly seems to work pretty well.

wtarreau commented 1 year ago

using a Rust library like WolfSSL

WolfSSL is C, not Rust. And it builds pretty fast (5 seconds or so). The main issue with WolfSSL is that it's not particularly dynamic, it was initially designed for embedded systems so it has a hundred or so of configure options and almost needs to be configured for the target use case. However its coverage of the openssl API seems to be pretty large (we do have regtests failing due to missing mappings but a lot of stuff seems there already). I think this lib just needs more users to start to figure what a generic use case could be and at least support being pre-built for such use cases and shipped as-is by distros.

ahmadkakarr commented 1 year ago

can't we add quic-go into this package. browsers also support this protocol now. https://caniuse.com/http3

32bitx64bit commented 1 year ago

Any news on this? All major browsers but safari ofc support it. I do believe this should be considered. As having standards is a must have in everything.

just a side note safari technically supports it in its development branch or known as "technology preview"