Skip to content

Commit e50a4c6

Browse files
committed
net/http: register HTTP/2 before listening in ListenAndServe
Change-Id: Icf9b6802945051aa484fb9ebcce71704f5655474 Reviewed-on: https://go-review.googlesource.com/16630 Reviewed-by: Andrew Gerrand <[email protected]> Run-TryBot: Brad Fitzpatrick <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 8ee90fa commit e50a4c6

File tree

6 files changed

+141
-48
lines changed

6 files changed

+141
-48
lines changed

src/go/build/deps_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ var pkgDeps = map[string][]string{
361361
"net/http/cgi": {"L4", "NET", "OS", "crypto/tls", "net/http", "regexp"},
362362
"net/http/cookiejar": {"L4", "NET", "net/http"},
363363
"net/http/fcgi": {"L4", "NET", "OS", "net/http", "net/http/cgi"},
364-
"net/http/httptest": {"L4", "NET", "OS", "crypto/tls", "flag", "net/http"},
364+
"net/http/httptest": {"L4", "NET", "OS", "crypto/tls", "flag", "net/http", "net/http/internal"},
365365
"net/http/httputil": {"L4", "NET", "OS", "net/http", "net/http/internal"},
366366
"net/http/pprof": {"L4", "OS", "html/template", "net/http", "runtime/pprof", "runtime/trace"},
367367
"net/rpc": {"L4", "NET", "encoding/gob", "html/template", "net/http"},

src/net/http/export_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,5 @@ var ExportCloseWriteAndWait = (*conn).closeWriteAndWait
132132
var ExportErrRequestCanceled = errRequestCanceled
133133

134134
var ExportServeFile = serveFile
135+
136+
func SetTestHookServerServe(fn func(*Server, net.Listener)) { testHookServerServe = fn }

src/net/http/httptest/server.go

Lines changed: 2 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"log"
1515
"net"
1616
"net/http"
17+
"net/http/internal"
1718
"os"
1819
"runtime"
1920
"sync"
@@ -107,7 +108,7 @@ func (s *Server) StartTLS() {
107108
if s.URL != "" {
108109
panic("Server already started")
109110
}
110-
cert, err := tls.X509KeyPair(localhostCert, localhostKey)
111+
cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey)
111112
if err != nil {
112113
panic(fmt.Sprintf("httptest: NewTLSServer: %v", err))
113114
}
@@ -289,39 +290,3 @@ func (s *Server) forgetConn(c net.Conn) {
289290
s.wg.Done()
290291
}
291292
}
292-
293-
// localhostCert is a PEM-encoded TLS cert with SAN IPs
294-
// "127.0.0.1" and "[::1]", expiring at Jan 29 16:00:00 2084 GMT.
295-
// generated from src/crypto/tls:
296-
// go run generate_cert.go --rsa-bits 1024 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
297-
var localhostCert = []byte(`-----BEGIN CERTIFICATE-----
298-
MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zANBgkqhkiG9w0BAQsFADAS
299-
MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
300-
MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
301-
iQKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9SjY1bIw4
302-
iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZBl2+XsDul
303-
rKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQABo2gwZjAO
304-
BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw
305-
AwEB/zAuBgNVHREEJzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAA
306-
AAAAATANBgkqhkiG9w0BAQsFAAOBgQCEcetwO59EWk7WiJsG4x8SY+UIAA+flUI9
307-
tyC4lNhbcF2Idq9greZwbYCqTTTr2XiRNSMLCOjKyI7ukPoPjo16ocHj+P3vZGfs
308-
h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM
309-
fblo6RBxUQ==
310-
-----END CERTIFICATE-----`)
311-
312-
// localhostKey is the private key for localhostCert.
313-
var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
314-
MIICXgIBAAKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9
315-
SjY1bIw4iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZB
316-
l2+XsDulrKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQAB
317-
AoGAGRzwwir7XvBOAy5tM/uV6e+Zf6anZzus1s1Y1ClbjbE6HXbnWWF/wbZGOpet
318-
3Zm4vD6MXc7jpTLryzTQIvVdfQbRc6+MUVeLKwZatTXtdZrhu+Jk7hx0nTPy8Jcb
319-
uJqFk541aEw+mMogY/xEcfbWd6IOkp+4xqjlFLBEDytgbIECQQDvH/E6nk+hgN4H
320-
qzzVtxxr397vWrjrIgPbJpQvBsafG7b0dA4AFjwVbFLmQcj2PprIMmPcQrooz8vp
321-
jy4SHEg1AkEA/v13/5M47K9vCxmb8QeD/asydfsgS5TeuNi8DoUBEmiSJwma7FXY
322-
fFUtxuvL7XvjwjN5B30pNEbc6Iuyt7y4MQJBAIt21su4b3sjXNueLKH85Q+phy2U
323-
fQtuUE9txblTu14q3N7gHRZB4ZMhFYyDy8CKrN2cPg/Fvyt0Xlp/DoCzjA0CQQDU
324-
y2ptGsuSmgUtWj3NM9xuwYPm+Z/F84K6+ARYiZ6PYj013sovGKUFfYAqVXVlxtIX
325-
qyUBnu3X9ps8ZfjLZO7BAkEAlT4R5Yl6cGhaJQYZHOde3JEMhNRcVFMO8dJDaFeo
326-
f9Oeos0UUothgiDktdQHxdNEwLjQf7lJJBzV+5OtwswCWA==
327-
-----END RSA PRIVATE KEY-----`)

src/net/http/internal/testcert.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright 2015 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package internal
6+
7+
// LocalhostCert is a PEM-encoded TLS cert with SAN IPs
8+
// "127.0.0.1" and "[::1]", expiring at Jan 29 16:00:00 2084 GMT.
9+
// generated from src/crypto/tls:
10+
// go run generate_cert.go --rsa-bits 1024 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
11+
var LocalhostCert = []byte(`-----BEGIN CERTIFICATE-----
12+
MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zANBgkqhkiG9w0BAQsFADAS
13+
MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
14+
MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
15+
iQKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9SjY1bIw4
16+
iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZBl2+XsDul
17+
rKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQABo2gwZjAO
18+
BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw
19+
AwEB/zAuBgNVHREEJzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAA
20+
AAAAATANBgkqhkiG9w0BAQsFAAOBgQCEcetwO59EWk7WiJsG4x8SY+UIAA+flUI9
21+
tyC4lNhbcF2Idq9greZwbYCqTTTr2XiRNSMLCOjKyI7ukPoPjo16ocHj+P3vZGfs
22+
h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM
23+
fblo6RBxUQ==
24+
-----END CERTIFICATE-----`)
25+
26+
// LocalhostKey is the private key for localhostCert.
27+
var LocalhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
28+
MIICXgIBAAKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9
29+
SjY1bIw4iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZB
30+
l2+XsDulrKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQAB
31+
AoGAGRzwwir7XvBOAy5tM/uV6e+Zf6anZzus1s1Y1ClbjbE6HXbnWWF/wbZGOpet
32+
3Zm4vD6MXc7jpTLryzTQIvVdfQbRc6+MUVeLKwZatTXtdZrhu+Jk7hx0nTPy8Jcb
33+
uJqFk541aEw+mMogY/xEcfbWd6IOkp+4xqjlFLBEDytgbIECQQDvH/E6nk+hgN4H
34+
qzzVtxxr397vWrjrIgPbJpQvBsafG7b0dA4AFjwVbFLmQcj2PprIMmPcQrooz8vp
35+
jy4SHEg1AkEA/v13/5M47K9vCxmb8QeD/asydfsgS5TeuNi8DoUBEmiSJwma7FXY
36+
fFUtxuvL7XvjwjN5B30pNEbc6Iuyt7y4MQJBAIt21su4b3sjXNueLKH85Q+phy2U
37+
fQtuUE9txblTu14q3N7gHRZB4ZMhFYyDy8CKrN2cPg/Fvyt0Xlp/DoCzjA0CQQDU
38+
y2ptGsuSmgUtWj3NM9xuwYPm+Z/F84K6+ARYiZ6PYj013sovGKUFfYAqVXVlxtIX
39+
qyUBnu3X9ps8ZfjLZO7BAkEAlT4R5Yl6cGhaJQYZHOde3JEMhNRcVFMO8dJDaFeo
40+
f9Oeos0UUothgiDktdQHxdNEwLjQf7lJJBzV+5OtwswCWA==
41+
-----END RSA PRIVATE KEY-----`)

src/net/http/serve_test.go

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1069,7 +1069,8 @@ func TestTLSServer(t *testing.T) {
10691069
})
10701070
}
10711071

1072-
func TestAutomaticHTTP2(t *testing.T) {
1072+
func TestAutomaticHTTP2_Serve(t *testing.T) {
1073+
defer afterTest(t)
10731074
ln := newLocalListener(t)
10741075
ln.Close() // immediately (not a defer!)
10751076
var s Server
@@ -1082,6 +1083,65 @@ func TestAutomaticHTTP2(t *testing.T) {
10821083
}
10831084
}
10841085

1086+
func TestAutomaticHTTP2_ListenAndServe(t *testing.T) {
1087+
defer afterTest(t)
1088+
defer SetTestHookServerServe(nil)
1089+
cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey)
1090+
if err != nil {
1091+
t.Fatal(err)
1092+
}
1093+
var ok bool
1094+
var s *Server
1095+
const maxTries = 5
1096+
var ln net.Listener
1097+
Try:
1098+
for try := 0; try < maxTries; try++ {
1099+
ln = newLocalListener(t)
1100+
addr := ln.Addr().String()
1101+
ln.Close()
1102+
t.Logf("Got %v", addr)
1103+
lnc := make(chan net.Listener, 1)
1104+
SetTestHookServerServe(func(s *Server, ln net.Listener) {
1105+
lnc <- ln
1106+
})
1107+
s = &Server{
1108+
Addr: addr,
1109+
TLSConfig: &tls.Config{
1110+
Certificates: []tls.Certificate{cert},
1111+
},
1112+
}
1113+
errc := make(chan error, 1)
1114+
go func() { errc <- s.ListenAndServeTLS("", "") }()
1115+
select {
1116+
case err := <-errc:
1117+
t.Logf("On try #%v: %v", try+1, err)
1118+
continue
1119+
case ln = <-lnc:
1120+
ok = true
1121+
t.Logf("Listening on %v", ln.Addr().String())
1122+
break Try
1123+
}
1124+
}
1125+
if !ok {
1126+
t.Fatal("Failed to start up after %d tries", maxTries)
1127+
}
1128+
defer ln.Close()
1129+
c, err := tls.Dial("tcp", ln.Addr().String(), &tls.Config{
1130+
InsecureSkipVerify: true,
1131+
NextProtos: []string{"h2", "http/1.1"},
1132+
})
1133+
if err != nil {
1134+
t.Fatal(err)
1135+
}
1136+
defer c.Close()
1137+
if got, want := c.ConnectionState().NegotiatedProtocol, "h2"; got != want {
1138+
t.Errorf("NegotiatedProtocol = %q; want %q", got, want)
1139+
}
1140+
if got, want := c.ConnectionState().NegotiatedProtocolIsMutual, true; got != want {
1141+
t.Errorf("NegotiatedProtocolIsMutual = %v; want %v", got, want)
1142+
}
1143+
}
1144+
10851145
type serverExpectTest struct {
10861146
contentLength int // of request body
10871147
chunked bool

src/net/http/server.go

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1899,17 +1899,20 @@ func (srv *Server) ListenAndServe() error {
18991899
return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
19001900
}
19011901

1902+
var testHookServerServe func(*Server, net.Listener) // used if non-nil
1903+
19021904
// Serve accepts incoming connections on the Listener l, creating a
19031905
// new service goroutine for each. The service goroutines read requests and
19041906
// then call srv.Handler to reply to them.
19051907
// Serve always returns a non-nil error.
19061908
func (srv *Server) Serve(l net.Listener) error {
19071909
defer l.Close()
1910+
if fn := testHookServerServe; fn != nil {
1911+
fn(srv, l)
1912+
}
19081913
var tempDelay time.Duration // how long to sleep on accept failure
1909-
srv.nextProtoOnce.Do(srv.setNextProtoDefaults)
1910-
if srv.nextProtoErr != nil {
1911-
// Error from http2 ConfigureServer (e.g. bad ciphersuites)
1912-
return srv.nextProtoErr
1914+
if err := srv.setupHTTP2(); err != nil {
1915+
return err
19131916
}
19141917
for {
19151918
rw, e := l.Accept()
@@ -2044,9 +2047,16 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
20442047
if addr == "" {
20452048
addr = ":https"
20462049
}
2050+
2051+
// Setup HTTP/2 before srv.Serve, to initialize srv.TLSConfig
2052+
// before we clone it and create the TLS Listener.
2053+
if err := srv.setupHTTP2(); err != nil {
2054+
return err
2055+
}
2056+
20472057
config := cloneTLSConfig(srv.TLSConfig)
2048-
if config.NextProtos == nil {
2049-
config.NextProtos = []string{"http/1.1"}
2058+
if !strSliceContains(config.NextProtos, "http/1.1") {
2059+
config.NextProtos = append(config.NextProtos, "http/1.1")
20502060
}
20512061

20522062
if len(config.Certificates) == 0 || certFile != "" || keyFile != "" {
@@ -2067,9 +2077,15 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
20672077
return srv.Serve(tlsListener)
20682078
}
20692079

2070-
// setNextProtoDefaults configures HTTP/2.
2071-
// It must only be called via srv.nextProtoOnce.
2072-
func (srv *Server) setNextProtoDefaults() {
2080+
func (srv *Server) setupHTTP2() error {
2081+
srv.nextProtoOnce.Do(srv.onceSetNextProtoDefaults)
2082+
return srv.nextProtoErr
2083+
}
2084+
2085+
// onceSetNextProtoDefaults configures HTTP/2, if the user hasn't
2086+
// configured otherwise. (by setting srv.TLSNextProto non-nil)
2087+
// It must only be called via srv.nextProtoOnce (use srv.setupHTTP2).
2088+
func (srv *Server) onceSetNextProtoDefaults() {
20732089
// Enable HTTP/2 by default if the user hasn't otherwise
20742090
// configured their TLSNextProto map.
20752091
if srv.TLSNextProto == nil {
@@ -2304,3 +2320,12 @@ func numLeadingCRorLF(v []byte) (n int) {
23042320
return
23052321

23062322
}
2323+
2324+
func strSliceContains(ss []string, s string) bool {
2325+
for _, v := range ss {
2326+
if v == s {
2327+
return true
2328+
}
2329+
}
2330+
return false
2331+
}

0 commit comments

Comments
 (0)