diff options
| author | Nicholas S. Husin <nsh@golang.org> | 2026-03-30 19:17:03 -0400 |
|---|---|---|
| committer | Nicholas Husin <nsh@golang.org> | 2026-04-10 08:24:28 -0700 |
| commit | 2f3c778b232dd53c41e1b623d25cd9f4ab28aaa5 (patch) | |
| tree | 3959d70ffde2c7c385b0cc5c62cb3ac56dbe1516 /src/net/http/httptest/server.go | |
| parent | ce4459cf0ee339b3bcf0ed10427079a234aade36 (diff) | |
| download | go-2f3c778b232dd53c41e1b623d25cd9f4ab28aaa5.tar.xz | |
net/http: add support for running HTTP tests against HTTP/3
Add support within clientserver_test.go to bring up a test HTTP/3 server
and client when http3Mode testMode option is passed.
To be able to reuse net/http/httptest, net/http/httptest.Server.StartTLS
(and Start) have been modified so they can be called with a nil
Listener. In such cases, both methods will behave identically as usual,
but will not actually make its server serve or set its transport dialer,
both of which requires having a listener. This should be a no-op for
regular users of the package, whose entrypoint via functions such as
NewServer will automatically set a local listener.
Actually enabling HTTP/3 for our tests will be done in a separate CL.
For #70914
Change-Id: Ibc5fc83287b6a04b46e668a54924761a92b620a4
Reviewed-on: https://go-review.googlesource.com/c/go/+/740122
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>
Diffstat (limited to 'src/net/http/httptest/server.go')
| -rw-r--r-- | src/net/http/httptest/server.go | 63 |
1 files changed, 37 insertions, 26 deletions
diff --git a/src/net/http/httptest/server.go b/src/net/http/httptest/server.go index 7ae2561b71..fd65e5797a 100644 --- a/src/net/http/httptest/server.go +++ b/src/net/http/httptest/server.go @@ -20,6 +20,7 @@ import ( "strings" "sync" "time" + _ "unsafe" // for linkname ) // A Server is an HTTP server listening on a system-chosen port on the @@ -45,6 +46,9 @@ type Server struct { // certificate is a parsed version of the TLS config certificate, if present. certificate *x509.Certificate + // started indicates whether the server has been started. + started bool + // wg counts the number of outstanding HTTP requests on this server. // Close blocks until all requests are finished. wg sync.WaitGroup @@ -124,30 +128,31 @@ func NewUnstartedServer(handler http.Handler) *Server { // Start starts a server from NewUnstartedServer. func (s *Server) Start() { - if s.URL != "" { + if s.started { panic("Server already started") } + s.started = true + s.wrap() - if s.client == nil { - tr := &http.Transport{} - dialer := net.Dialer{} - // User code may set either of Dial or DialContext, with DialContext taking precedence. - // We set DialContext here to preserve any context values that are passed in, - // but fall back to Dial if the user has set it. - tr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) { - if tr.Dial != nil { - return tr.Dial(network, addr) - } - if addr == "example.com:80" || strings.HasSuffix(addr, ".example.com:80") { - addr = s.Listener.Addr().String() - } - return dialer.DialContext(ctx, network, addr) + tr := &http.Transport{} + s.client = &http.Client{Transport: tr} + if s.Listener == nil { + return + } + dialer := net.Dialer{} + // User code may set either of Dial or DialContext, with DialContext taking precedence. + // We set DialContext here to preserve any context values that are passed in, + // but fall back to Dial if the user has set it. + tr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) { + if tr.Dial != nil { + return tr.Dial(network, addr) } - s.client = &http.Client{Transport: tr} - + if addr == "example.com:80" || strings.HasSuffix(addr, ".example.com:80") { + addr = s.Listener.Addr().String() + } + return dialer.DialContext(ctx, network, addr) } s.URL = "http://" + s.Listener.Addr().String() - s.wrap() s.goServe() if serveFlag != "" { fmt.Fprintln(os.Stderr, "httptest: serving on", s.URL) @@ -157,12 +162,13 @@ func (s *Server) Start() { // StartTLS starts TLS on a server from NewUnstartedServer. func (s *Server) StartTLS() { - if s.URL != "" { + if s.started { panic("Server already started") } - if s.client == nil { - s.client = &http.Client{} - } + s.started = true + s.wrap() + + s.client = &http.Client{} cert, err := tls.X509KeyPair(testcert.LocalhostCert, testcert.LocalhostKey) if err != nil { panic(fmt.Sprintf("httptest: NewTLSServer: %v", err)) @@ -190,12 +196,18 @@ func (s *Server) StartTLS() { } certpool := x509.NewCertPool() certpool.AddCert(s.certificate) + tr := &http.Transport{ TLSClientConfig: &tls.Config{ RootCAs: certpool, }, ForceAttemptHTTP2: s.EnableHTTP2, } + s.client.Transport = tr + + if s.Listener == nil { + return + } dialer := net.Dialer{} tr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) { if tr.Dial != nil { @@ -206,10 +218,8 @@ func (s *Server) StartTLS() { } return dialer.DialContext(ctx, network, addr) } - s.client.Transport = tr s.Listener = tls.NewListener(s.Listener, s.TLS) s.URL = "https://" + s.Listener.Addr().String() - s.wrap() s.goServe() } @@ -231,7 +241,9 @@ func (s *Server) Close() { s.mu.Lock() if !s.closed { s.closed = true - s.Listener.Close() + if s.Listener != nil { + s.Listener.Close() + } s.Config.SetKeepAlivesEnabled(false) for c, st := range s.conns { // Force-close any idle connections (those between @@ -275,7 +287,6 @@ func (s *Server) Close() { t.CloseIdleConnections() } } - s.wg.Wait() } |
