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>
This commit is contained in:
Nicholas S. Husin
2026-01-23 15:14:30 -05:00
committed by Nicholas Husin
parent f2078620ee
commit 6b849cc122
2 changed files with 19 additions and 5 deletions

View File

@@ -7,6 +7,7 @@ package http3
import (
"context"
"net/http"
"net/url"
"strconv"
"sync"
@@ -156,8 +157,13 @@ func (sc *serverConn) handlePushStream(*stream) error {
}
}
func parseRequest(st *stream) (*http.Request, error) {
req := &http.Request{}
func (sc *serverConn) parseRequest(st *stream) (*http.Request, error) {
req := &http.Request{
URL: &url.URL{},
Proto: "HTTP/3.0",
ProtoMajor: 3,
RemoteAddr: sc.qconn.RemoteAddr().String(),
}
ftype, err := st.readFrameHeader()
if err != nil {
return nil, err
@@ -195,7 +201,7 @@ func parseRequest(st *stream) (*http.Request, error) {
}
func (sc *serverConn) handleRequestStream(st *stream) error {
req, err := parseRequest(st)
req, err := sc.parseRequest(st)
if err != nil {
return err
}

View File

@@ -68,6 +68,7 @@ func TestServerHeader(t *testing.T) {
":status": {"204"},
"Header-From-Client": {"that", "should", "be", "echoed"},
})
reqStream.wantClosed("request is complete")
})
}
@@ -92,6 +93,7 @@ func TestServerPseudoHeader(t *testing.T) {
reqStream.writeHeaders(http.Header{":method": {"GET"}})
synctest.Wait()
reqStream.wantHeaders(map[string][]string{":status": {"321"}})
reqStream.wantClosed("request is complete")
})
}
@@ -116,6 +118,7 @@ func TestServerInvalidHeader(t *testing.T) {
"Valid-Name": {"valid value"},
"Valid-Name-2": {"valid value 2"},
})
reqStream.wantClosed("request is complete")
})
}
@@ -126,19 +129,24 @@ func TestServerBody(t *testing.T) {
if err != nil {
t.Fatal(err)
}
w.Write(body) // Implicitly calls w.WriteHeader(200).
w.Write([]byte(r.URL.Path)) // Implicitly calls w.WriteHeader(200).
w.Write(body)
}))
tc := ts.connect()
tc.greet()
reqStream := tc.newStream(streamTypeRequest)
reqStream.writeHeaders(http.Header{})
reqStream.writeHeaders(http.Header{
":path": {"/"},
})
bodyContent := []byte("some body content that should be echoed")
reqStream.writeData(bodyContent)
reqStream.stream.stream.CloseWrite()
synctest.Wait()
reqStream.wantHeaders(http.Header{":status": {"200"}})
reqStream.wantData([]byte("/"))
reqStream.wantData(bodyContent)
reqStream.wantClosed("request is complete")
})
}