aboutsummaryrefslogtreecommitdiff
path: root/src/net/http/httptest/server.go
diff options
context:
space:
mode:
authorNicholas S. Husin <nsh@golang.org>2026-03-30 19:17:03 -0400
committerNicholas Husin <nsh@golang.org>2026-04-10 08:24:28 -0700
commit2f3c778b232dd53c41e1b623d25cd9f4ab28aaa5 (patch)
tree3959d70ffde2c7c385b0cc5c62cb3ac56dbe1516 /src/net/http/httptest/server.go
parentce4459cf0ee339b3bcf0ed10427079a234aade36 (diff)
downloadgo-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.go63
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()
}