http2: don't panic when ServeConn is passed a nil options
Fixes golang/go#75286
Change-Id: I91e6a0a61234c81f809b74151946dddde9099078
Reviewed-on: https://go-review.googlesource.com/c/net/+/700999
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Nicholas Husin <nsh@golang.org>
Reviewed-by: Nicholas Husin <husin@google.com>
Auto-Submit: Nicholas Husin <nsh@golang.org>
diff --git a/http2/http2_test.go b/http2/http2_test.go
index d263c1b..cd86fa8 100644
--- a/http2/http2_test.go
+++ b/http2/http2_test.go
@@ -287,7 +287,7 @@
}
// setForTest sets *p = v, and restores its original value in t.Cleanup.
-func setForTest[T any](t *testing.T, p *T, v T) {
+func setForTest[T any](t testing.TB, p *T, v T) {
orig := *p
t.Cleanup(func() {
*p = orig
diff --git a/http2/server.go b/http2/server.go
index 7c5c466..3d41353 100644
--- a/http2/server.go
+++ b/http2/server.go
@@ -390,6 +390,9 @@
//
// The opts parameter is optional. If nil, default values are used.
func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
+ if opts == nil {
+ opts = &ServeConnOpts{}
+ }
s.serveConn(c, opts, nil)
}
diff --git a/http2/server_test.go b/http2/server_test.go
index 9b028de..a60e717 100644
--- a/http2/server_test.go
+++ b/http2/server_test.go
@@ -3266,26 +3266,47 @@
func (c *issue53Conn) SetReadDeadline(t time.Time) error { return nil }
func (c *issue53Conn) SetWriteDeadline(t time.Time) error { return nil }
+// TestServeConnNilOpts ensures that Server.ServeConn(conn, nil) works.
+//
// golang.org/issue/33839
-func TestServeConnOptsNilReceiverBehavior(t *testing.T) {
- synctestTest(t, testServeConnOptsNilReceiverBehavior)
-}
-func testServeConnOptsNilReceiverBehavior(t testing.TB) {
- defer func() {
- if r := recover(); r != nil {
- t.Errorf("got a panic that should not happen: %v", r)
- }
- }()
+func TestServeConnNilOpts(t *testing.T) { synctestTest(t, testServeConnNilOpts) }
+func testServeConnNilOpts(t testing.TB) {
+ // A nil ServeConnOpts uses http.DefaultServeMux as the handler.
+ var gotRequest string
+ var mux http.ServeMux
+ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ gotRequest = r.URL.Path
+ })
+ setForTest(t, &http.DefaultServeMux, &mux)
- var o *ServeConnOpts
- if o.context() == nil {
- t.Error("o.context should not return nil")
- }
- if o.baseConfig() == nil {
- t.Error("o.baseConfig should not return nil")
- }
- if o.handler() == nil {
- t.Error("o.handler should not return nil")
+ srvConn, cliConn := net.Pipe()
+ defer srvConn.Close()
+ defer cliConn.Close()
+
+ s2 := &Server{}
+ go s2.ServeConn(srvConn, nil)
+
+ fr := NewFramer(cliConn, cliConn)
+ io.WriteString(cliConn, ClientPreface)
+ fr.WriteSettings()
+ fr.WriteSettingsAck()
+ var henc hpackEncoder
+ const reqPath = "/request"
+ fr.WriteHeaders(HeadersFrameParam{
+ StreamID: 1,
+ BlockFragment: henc.encodeHeaderRaw(t,
+ ":method", "GET",
+ ":path", reqPath,
+ ":scheme", "https",
+ ":authority", "foo.com",
+ ),
+ EndStream: true,
+ EndHeaders: true,
+ })
+
+ synctest.Wait()
+ if got, want := gotRequest, reqPath; got != want {
+ t.Errorf("got request: %q, want %q", got, want)
}
}