1 // Copyright 2011 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.
5 // Implementation of Server
19 // A Server is an HTTP server listening on a system-chosen port on the
20 // local loopback interface, for use in end-to-end HTTP tests.
22 URL
string // base URL of form http://ipaddr:port with no trailing slash
25 // TLS is the optional TLS configuration, populated with a new config
26 // after TLS is started. If set on an unstarted server before StartTLS
27 // is called, existing fields are copied into the new config.
30 // Config may be changed after calling NewUnstartedServer and
31 // before Start or StartTLS.
34 // wg counts the number of outstanding HTTP requests on this server.
35 // Close blocks until all requests are finished.
39 // historyListener keeps track of all connections that it's ever
41 type historyListener
struct {
43 sync
.Mutex
// protects history
47 func (hs
*historyListener
) Accept() (c net
.Conn
, err error
) {
48 c
, err
= hs
.Listener
.Accept()
51 hs
.history
= append(hs
.history
, c
)
57 func newLocalListener() net
.Listener
{
59 l
, err
:= net
.Listen("tcp", *serve
)
61 panic(fmt
.Sprintf("httptest: failed to listen on %v: %v", *serve
, err
))
65 l
, err
:= net
.Listen("tcp", "127.0.0.1:0")
67 if l
, err
= net
.Listen("tcp6", "[::1]:0"); err
!= nil {
68 panic(fmt
.Sprintf("httptest: failed to listen on a port: %v", err
))
74 // When debugging a particular http server-based test,
75 // this flag lets you run
76 // go test -run=BrokenTest -httptest.serve=127.0.0.1:8000
77 // to start the broken server so you can interact with it manually.
78 var serve
= flag
.String("httptest.serve", "", "if non-empty, httptest.NewServer serves on this address and blocks")
80 // NewServer starts and returns a new Server.
81 // The caller should call Close when finished, to shut it down.
82 func NewServer(handler http
.Handler
) *Server
{
83 ts
:= NewUnstartedServer(handler
)
88 // NewUnstartedServer returns a new Server but doesn't start it.
90 // After changing its configuration, the caller should call Start or
93 // The caller should call Close when finished, to shut it down.
94 func NewUnstartedServer(handler http
.Handler
) *Server
{
96 Listener
: newLocalListener(),
97 Config
: &http
.Server
{Handler
: handler
},
101 // Start starts a server from NewUnstartedServer.
102 func (s
*Server
) Start() {
104 panic("Server already started")
106 s
.Listener
= &historyListener
{Listener
: s
.Listener
}
107 s
.URL
= "http://" + s
.Listener
.Addr().String()
109 go s
.Config
.Serve(s
.Listener
)
111 fmt
.Fprintln(os
.Stderr
, "httptest: serving on", s
.URL
)
116 // StartTLS starts TLS on a server from NewUnstartedServer.
117 func (s
*Server
) StartTLS() {
119 panic("Server already started")
121 cert
, err
:= tls
.X509KeyPair(localhostCert
, localhostKey
)
123 panic(fmt
.Sprintf("httptest: NewTLSServer: %v", err
))
126 existingConfig
:= s
.TLS
127 s
.TLS
= new(tls
.Config
)
128 if existingConfig
!= nil {
129 *s
.TLS
= *existingConfig
131 if s
.TLS
.NextProtos
== nil {
132 s
.TLS
.NextProtos
= []string{"http/1.1"}
134 if len(s
.TLS
.Certificates
) == 0 {
135 s
.TLS
.Certificates
= []tls
.Certificate
{cert
}
137 tlsListener
:= tls
.NewListener(s
.Listener
, s
.TLS
)
139 s
.Listener
= &historyListener
{Listener
: tlsListener
}
140 s
.URL
= "https://" + s
.Listener
.Addr().String()
142 go s
.Config
.Serve(s
.Listener
)
145 func (s
*Server
) wrapHandler() {
146 h
:= s
.Config
.Handler
148 h
= http
.DefaultServeMux
150 s
.Config
.Handler
= &waitGroupHandler
{
156 // NewTLSServer starts and returns a new Server using TLS.
157 // The caller should call Close when finished, to shut it down.
158 func NewTLSServer(handler http
.Handler
) *Server
{
159 ts
:= NewUnstartedServer(handler
)
164 // Close shuts down the server and blocks until all outstanding
165 // requests on this server have completed.
166 func (s
*Server
) Close() {
169 s
.CloseClientConnections()
170 if t
, ok
:= http
.DefaultTransport
.(*http
.Transport
); ok
{
171 t
.CloseIdleConnections()
175 // CloseClientConnections closes any currently open HTTP connections
176 // to the test Server.
177 func (s
*Server
) CloseClientConnections() {
178 hl
, ok
:= s
.Listener
.(*historyListener
)
183 for _
, conn
:= range hl
.history
{
189 // waitGroupHandler wraps a handler, incrementing and decrementing a
190 // sync.WaitGroup on each request, to enable Server.Close to block
191 // until outstanding requests are finished.
192 type waitGroupHandler
struct {
194 h http
.Handler
// non-nil
197 func (h
*waitGroupHandler
) ServeHTTP(w http
.ResponseWriter
, r
*http
.Request
) {
199 defer h
.s
.wg
.Done() // a defer, in case ServeHTTP below panics
203 // localhostCert is a PEM-encoded TLS cert with SAN IPs
204 // "127.0.0.1" and "[::1]", expiring at the last second of 2049 (the end
206 // generated from src/pkg/crypto/tls:
207 // go run generate_cert.go --rsa-bits 512 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
208 var localhostCert
= []byte(`-----BEGIN CERTIFICATE-----
209 MIIBdzCCASOgAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
210 bzAeFw03MDAxMDEwMDAwMDBaFw00OTEyMzEyMzU5NTlaMBIxEDAOBgNVBAoTB0Fj
211 bWUgQ28wWjALBgkqhkiG9w0BAQEDSwAwSAJBAN55NcYKZeInyTuhcCwFMhDHCmwa
212 IUSdtXdcbItRB/yfXGBhiex00IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEA
213 AaNoMGYwDgYDVR0PAQH/BAQDAgCkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1Ud
214 EwEB/wQFMAMBAf8wLgYDVR0RBCcwJYILZXhhbXBsZS5jb22HBH8AAAGHEAAAAAAA
215 AAAAAAAAAAAAAAEwCwYJKoZIhvcNAQEFA0EAAoQn/ytgqpiLcZu9XKbCJsJcvkgk
216 Se6AbGXgSlq+ZCEVo0qIwSgeBqmsJxUu7NCSOwVJLYNEBO2DtIxoYVk+MA==
217 -----END CERTIFICATE-----`)
219 // localhostKey is the private key for localhostCert.
220 var localhostKey
= []byte(`-----BEGIN RSA PRIVATE KEY-----
221 MIIBPAIBAAJBAN55NcYKZeInyTuhcCwFMhDHCmwaIUSdtXdcbItRB/yfXGBhiex0
222 0IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEAAQJBAQdUx66rfh8sYsgfdcvV
223 NoafYpnEcB5s4m/vSVe6SU7dCK6eYec9f9wpT353ljhDUHq3EbmE4foNzJngh35d
224 AekCIQDhRQG5Li0Wj8TM4obOnnXUXf1jRv0UkzE9AHWLG5q3AwIhAPzSjpYUDjVW
225 MCUXgckTpKCuGwbJk7424Nb8bLzf3kllAiA5mUBgjfr/WtFSJdWcPQ4Zt9KTMNKD
226 EUO0ukpTwEIl6wIhAMbGqZK3zAAFdq8DD2jPx+UJXnh0rnOkZBzDtJ6/iN69AiEA
227 1Aq8MJgTaYsDQWyU/hDq5YkDJc9e9DSCvUIzqxQWMQE=
228 -----END RSA PRIVATE KEY-----`)