29 Commits

Author SHA1 Message Date
Nicholas S. Husin
4a490d4f53 internal/http3: add Expect: 100-continue support to ClientConn
When sending a request containing the "Expect: 100-continue" header,
ClientConn.RoundTrip will now only send the request body after receiving
an HTTP 100 status response from the server.

For golang/go#70914

Change-Id: Ib3acea68b078486bda96426952897c3f2d51b47b
Reviewed-on: https://go-review.googlesource.com/c/net/+/742540
Reviewed-by: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Nicholas Husin <husin@google.com>
2026-02-06 16:20:02 -08:00
Nicholas S. Husin
73fe7011ad internal/http3: add Expect: 100-continue support to Server
When serving a request containing the "Expect: 100-continue" header,
Server will now send an HTTP 100 status automatically if the request
body is read from within the server handler.

For golang/go#70914

Change-Id: Ib8185170deabf777a02487a1ded6671db720df51
Reviewed-on: https://go-review.googlesource.com/c/net/+/742520
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Nicholas Husin <husin@google.com>
2026-02-06 16:19:57 -08:00
Nicholas S. Husin
e02fb33933 internal/http3: make responseWriter.Flush write headers if not done yet
In net/http and x/net/http2, flushing an http.ResponseWriter will also
trigger headers to be written if none has been written yet at that
point. This behavior is sometimes relied on when implementing streaming
responses (see http://go.dev/cl/4552062); therefore, let's do this in
x/net/internal/http3 too.

For golang/go#70914

Change-Id: Ib914afc85df21a1cddd1d5019311d3f25d943f8a
Reviewed-on: https://go-review.googlesource.com/c/net/+/742160
Reviewed-by: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Nicholas Husin <husin@google.com>
2026-02-05 18:42:21 -08:00
Nicholas S. Husin
da558ff100 internal/http3: ensure bodyReader cannot be read after being closed
Closing bodyReader currently only closes the underlying QUIC stream. As
a result, any unread data that was written to bodyStream prior to it
being closed can still be read. This is inconsistent with how we expect
net/http.Response.Body to behave.

For golang/go#70914

Change-Id: I58226c0d23ea3bbd97f3ceb5c3659e91660f84c5
Reviewed-on: https://go-review.googlesource.com/c/net/+/741982
Reviewed-by: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Nicholas Husin <husin@google.com>
2026-02-05 18:42:11 -08:00
Nicholas S. Husin
d7c76faf07 internal/http3: make responseWriter behave closer to other http.ResponseWriter
While running net/http tests against our HTTP/3 implementation locally,
some tests fail due to slight behavior differences in responseWriter
compared to other http.ResponseWriter implementations:

- responseWriter does not return a 200 OK response if a server handler
  is completely empty.
- responseWriter does not have a Flush method, and therefore does not
  implement http.Flusher.

There are surely more differences, but these are straightforward to fix
right now.

For golang/go#70914

Change-Id: Ieb729a4de4ccb55d670eac2369e73c240b9ac8f8
Reviewed-on: https://go-review.googlesource.com/c/net/+/741720
Reviewed-by: Nicholas Husin <husin@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Damien Neil <dneil@google.com>
2026-02-03 11:53:50 -08:00
Nicholas S. Husin
1973e8da2d internal/http3: add Server support for handling HEAD requests
When handling HEAD requests, Server will now always send an HTTP
response with an empty body, even if the HTTP handler would normally
write to the body.

For golang/go#70914

Change-Id: Id656a8f9901b97357a343e204761f6a47f87f9fe
Reviewed-on: https://go-review.googlesource.com/c/net/+/740160
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Nicholas Husin <husin@google.com>
2026-01-29 09:40:02 -08:00
Nicholas S. Husin
6b849cc122 internal/http3: populate some http.Request fields
Currently, we are passing a very barebone http.Request to the server
handler: we only initialize an empty http.Request and put whatever info
we can get while decoding QPACK headers.

Unfortunately, this causes the Server to panic when parsing requests
whose headers are meant to be written to http.Request.URL, as
http.Request.URL was never initialized.

Therefore, make sure that http.Request.URL is initialized. Also,
populate other http.Request fields that we can easily figure out as of
now.

For golang/go#70914

Change-Id: Ie6552d6678b430fe4b51069616c0e366791c4e34
Reviewed-on: https://go-review.googlesource.com/c/net/+/738880
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Nicholas Husin <husin@google.com>
2026-01-23 12:44:29 -08:00
Nicholas S. Husin
6640454869 internal/http3: break dependency on internal/quic/quicwire
internal/http3 currently depends on internal/quic/quicwire only for its
SizeVarint when writing SETTINGS frame. This makes bundling
internal/http3 into std more complicated since it forces us to also
bundle internal/quic/quicwire and do import remapping. This CL breaks
this dependency for easier bundling.

Dependency on internal/quic/quicwire in test codes have been left alone
since they do not affect bundling into std, and uses more than just
SizeVarint.

Change-Id: I2b85c5487ae6cce422deb4509f68f932d3f0de6b
Reviewed-on: https://go-review.googlesource.com/c/net/+/738060
Reviewed-by: Nicholas Husin <husin@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Damien Neil <dneil@google.com>
2026-01-21 14:58:16 -08:00
Nicholas S. Husin
c082574f2d internal/http3: remove GODEBUG=asynctimerchan=0 that is no longer needed
Change-Id: I86e83567b1d07fbc96ac98e0a85eb80748512eef
Reviewed-on: https://go-review.googlesource.com/c/net/+/737520
Reviewed-by: Carlos Amedee <carlos@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Damien Neil <dneil@google.com>
2026-01-20 09:02:49 -08:00
Nicholas S. Husin
15b99c1fb8 internal/http3: add basic request stream handling for the server
Add support for the server to handle basic request streams.
Specifically, reading HTTP headers & body in requests, and writing HTTP
headers & body in responses.

More sophisticated behaviors, such as dealing with 1xx status and
trailing headers, will be done in the future.

For golang/go#70914

Change-Id: I6a00435d72a118efe2ab76e4c7c53b9dca1d63f6
Reviewed-on: https://go-review.googlesource.com/c/net/+/735820
Reviewed-by: Nicholas Husin <husin@google.com>
Auto-Submit: Nicholas Husin <husin@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2026-01-13 07:38:07 -08:00
Nicholas S. Husin
eea413e294 internal/http3: use go1.25 synctest.Test instead of go1.24 synctest.Run
internal/http3 was written back in go1.24, and relies on synctest.Run
and goexperiment.synctest. This prevents us from running tests with
newer versions of Go.

This CL updates the existing build constraint and synctest usages to
go1.25 so we can still run tests using go1.25 and tip. Support for
running synctest with go1.24 is not kept, since go1.26 release (and
therefore x/net go.mod updating to go1.25) is expected soon.

Change-Id: Iebfa82ebd1da4a06ba613ce0f45051f4691037fc
Reviewed-on: https://go-review.googlesource.com/c/net/+/734940
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Nicholas Husin <husin@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2026-01-09 07:13:59 -08:00
cuishuang
875d966983 all: fix some comments
Including mismatched function names/struct names, repeated words, typos, etc.

Change-Id: Ia576274bce6e6fbfe4d2fca6dcd6d31bf00936fb
Reviewed-on: https://go-review.googlesource.com/c/net/+/683875
Auto-Submit: Sean Liao <sean@liao.dev>
Reviewed-by: Mark Freeman <markfreeman@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Sean Liao <sean@liao.dev>
2025-09-15 17:28:39 -07:00
Damien Neil
ef33bc08f8 internal/http3: use bubbled context in synctest tests
Avoid using T.Context within a synctest bubble. If the Context's
Done channel is created outside the bubble, waiting on it within
the bubble is durably blocking. If it's created within the bubble,
the testing package encounters a panic when closing it after
CL 671960.

Instead, create our own Context within the bubble and cancel it
before the bubble is destroyed.

This will be entirely obviated by synctest.Test, which creates
a testing.T that returns a properly bubbled context.

Change-Id: Iff93c296ccbc1ece8172cb0a60e626ea1bd895ad
Reviewed-on: https://go-review.googlesource.com/c/net/+/675615
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Damien Neil <dneil@google.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
2025-05-22 15:58:59 -07:00
Chressie Himpel
ebed060e8f internal/http3: fix build of tests with GOEXPERIMENT=nosynctest
The tests in qpack_decode_test.go require synctest helpers from
http3_test.go, but that file has a goexperiment.synctest build
constraint.

To make builds work when GOEXPERIMENT=nosynctest is specified the
synctest helpers are refactored into http3_synctest_test.go (with the
same build constraint) and the non-synctest related functionality is
kept in http3_test.go.

Change-Id: Iae339dc1895f27e7ac5ba985e204f4868c229a4d
Reviewed-on: https://go-review.googlesource.com/c/net/+/660535
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Damien Neil <dneil@google.com>
2025-03-25 08:01:24 -07:00
Damien Neil
459513d1f8 internal/http3: move more common stream processing to genericConn
Move the server stream-accept loop into genericConn.
(Overlooked in a previous CL.)

Be more consistent about having genericConn handle errors.

For golang/go#70914

Change-Id: I872673482f16539e95a1a1381ada7d3e22affb82
Reviewed-on: https://go-review.googlesource.com/c/net/+/653395
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Damien Neil <dneil@google.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
2025-02-28 11:43:44 -08:00
Damien Neil
5f45c776a9 internal/http3: make read-data tests usable for server handlers
A reading a transport response body behaves much the same as a
server handler reading a request body. Move the transport test into
body_test.go and rearrange it a bit so we can reuse it as a server
test.

For golang/go#70914

Change-Id: I24e10dd078ffab867c9b678e1d0b99172763b069
Reviewed-on: https://go-review.googlesource.com/c/net/+/652457
Auto-Submit: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
2025-02-27 10:24:19 -08:00
Damien Neil
163d83654d internal/http3: add Server
Add the general structure of an HTTP/3 server.
The server currently accepts QUIC connections and establishes a
control stream on them, but does not handle requests.

For golang/go#70914

Change-Id: I28193ddacef028233248601979b0b45ad844205a
Reviewed-on: https://go-review.googlesource.com/c/net/+/646617
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
2025-02-18 14:25:14 -08:00
Damien Neil
884432780b internal/httpcommon: don't depend on net/http
When the http2 package is bundled into net/http, it imports httpcommon,
so httpcommon must not depend on net/http.

Change-Id: I2aa34e913a0df757fa83deb56f650394a924933e
Reviewed-on: https://go-review.googlesource.com/c/net/+/649415
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
2025-02-13 14:27:35 -08:00
Damien Neil
b914489dfb internal/http3: refactor in prep for sharing transport/server code
Pull out various elements of the HTTP/3 client that can be
reused in the server. Move tests which can apply to client or server
connections into conn_test.go.

For golang/go#70914

Change-Id: I72b5eab55ba27df980ab2079120613f175b05927
Reviewed-on: https://go-review.googlesource.com/c/net/+/646616
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Auto-Submit: Damien Neil <dneil@google.com>
2025-02-04 17:21:19 -08:00
Damien Neil
938a9fb94e internal/http3: add request/response body transfer
For golang/go#70914

Change-Id: I372458214fe73f8156e0ec291168b043c10221e6
Reviewed-on: https://go-review.googlesource.com/c/net/+/644915
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Damien Neil <dneil@google.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
2025-02-03 17:39:20 -08:00
Damien Neil
145b2d7b6d internal/http3: add RoundTrip
Send request headers, receive response headers.

For golang/go#70914

Change-Id: I78d4dcc69c253ed7ad1543dfc3c5d8f1c321ced9
Reviewed-on: https://go-review.googlesource.com/c/net/+/644118
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Auto-Submit: Damien Neil <dneil@google.com>
2025-01-27 16:46:54 -08:00
Damien Neil
5bda71aec0 internal/http3: define connection and stream error types
HTTP/3 distinguishes between connection errors which result in an
entire connection closing, and stream errors which only terminate
a single request stream.

Define internal types to represent these two types of error.

For golang/go#70914

Change-Id: I907f395adc82a683b5c2eda65f936b1ab4904ffb
Reviewed-on: https://go-review.googlesource.com/c/net/+/644117
Reviewed-by: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Damien Neil <dneil@google.com>
2025-01-24 14:20:07 -08:00
Damien Neil
3c1185a39b internal/http3: return error on mid-frame EOF
When a stream ends in the middle of a frame,
return a non-EOF error from Read or ReadByte.

When a stream ends at the end of a frame,
don't return io.EOF from the Read call that reads
the last byte of the frame.
(This complicates stream.Read slightly,
but means that code that reads frames consistently
never sees an io.EOF, but gets an error if it tries
to read past the end of a frame.)

For golang/go#70914

Change-Id: If1b852716fe5e3aa3503f6970e2e1fba2ebb5f48
Reviewed-on: https://go-review.googlesource.com/c/net/+/644116
Auto-Submit: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
2025-01-24 14:05:38 -08:00
Damien Neil
c72e89d6a9 internal/http3: QPACK encoding and decoding
Basic support for encoding/decoding QPACK headers.

QPACK supports three forms of header compression:
Huffman-encoding of literal strings, a static table of
well-known header values, and a dynamic table of
header values negotiated between encoder and decoder
at runtime.

Right now, we support Huffman compression and the
static table, but not the dynamic table.
This is a supported mode for a QPACK encoder or
decoder, so we can leave dynamic table support
for after the rest of HTTP/3 is working.

For golang/go#70914

Change-Id: Ib694199b99c752a220d43f3a309169b16020b474
Reviewed-on: https://go-review.googlesource.com/c/net/+/642599
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Damien Neil <dneil@google.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2025-01-22 16:02:30 -08:00
Damien Neil
93c1957e42 internal/http3: add Transport and ClientConn
Add the first rudiments of an HTTP/3 client.

The client currently opens a QUIC connection and creates a control
stream on it, and nothing else.

Add surrounding test infrastructure for examining the client's
behavior. Tests use the experimental testing/synctest package
and will only run when the Go version is at least Go 1.24 and
GOEXPERIMENT=synctest is set.

For golang/go#70914

Change-Id: I19803187a8e62c461f60d7a1d44c2a408377e342
Reviewed-on: https://go-review.googlesource.com/c/net/+/642516
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Auto-Submit: Damien Neil <dneil@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-01-22 10:00:23 -08:00
Damien Neil
7ad0ebf002 internal/http3: qpack wire primitives
Encode and decode QPACK prefixed integers and string literals.

For golang/go#70914

Change-Id: Id12d1853738fc6d0e03bbbef36b67c24298451e1
Reviewed-on: https://go-review.googlesource.com/c/net/+/642115
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Auto-Submit: Damien Neil <dneil@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-01-13 15:50:20 -08:00
Damien Neil
f6b2e53bb7 internal/http3: basic stream read/write operations
Read and write HTTP/3 frames from QUIC streams.

The varint encoding/decoding overlaps a bit with that in
the quic package, but this package operates on streams while
the QUIC package operates on []bytes.

For golang/go#70914

Change-Id: I31115f5b572a59b899e2c880ecc86ba3caed982e
Reviewed-on: https://go-review.googlesource.com/c/net/+/641838
Auto-Submit: Damien Neil <dneil@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-01-13 15:50:17 -08:00
Damien Neil
78717f922a internal/http3: error codes
Define constants for RFC 9114 and RFC 9204 error codes.

For golang/go#70914

Change-Id: Icddaf0ef1468adc6ac8e7b8739d45c8e4400f0e4
Reviewed-on: https://go-review.googlesource.com/c/net/+/641837
Auto-Submit: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
2025-01-13 15:38:51 -08:00
Damien Neil
84b528b4a5 internal/http3: new package
Create a package for an HTTP/3 implementation.
Internal for now, intended to eventually move to x/net/http3.

For golang/go#70914

Change-Id: I3a643fe7958cf75b231ca97f25e9f338554f723c
Reviewed-on: https://go-review.googlesource.com/c/net/+/641836
Auto-Submit: Damien Neil <dneil@google.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-01-13 15:38:49 -08:00