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
14
"launchpad.net/ubuntu-push/http13client"
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-----`)