Source file src/pkg/net/http/httptest/server.go
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. 4 5 // Implementation of Server 6 7 package httptest 8 9 import ( 10 "crypto/tls" 11 "flag" 12 "fmt" 13 "net" 14 "net/http" 15 "os" 16 "sync" 17 ) 18 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. 21 type Server struct { 22 URL string // base URL of form http://ipaddr:port with no trailing slash 23 Listener net.Listener 24 TLS *tls.Config // nil if not using using TLS 25 26 // Config may be changed after calling NewUnstartedServer and 27 // before Start or StartTLS. 28 Config *http.Server 29 30 // wg counts the number of outstanding HTTP requests on this server. 31 // Close blocks until all requests are finished. 32 wg sync.WaitGroup 33 } 34 35 // historyListener keeps track of all connections that it's ever 36 // accepted. 37 type historyListener struct { 38 net.Listener 39 history []net.Conn 40 } 41 42 func (hs *historyListener) Accept() (c net.Conn, err error) { 43 c, err = hs.Listener.Accept() 44 if err == nil { 45 hs.history = append(hs.history, c) 46 } 47 return 48 } 49 50 func newLocalListener() net.Listener { 51 if *serve != "" { 52 l, err := net.Listen("tcp", *serve) 53 if err != nil { 54 panic(fmt.Sprintf("httptest: failed to listen on %v: %v", *serve, err)) 55 } 56 return l 57 } 58 l, err := net.Listen("tcp", "127.0.0.1:0") 59 if err != nil { 60 if l, err = net.Listen("tcp6", "[::1]:0"); err != nil { 61 panic(fmt.Sprintf("httptest: failed to listen on a port: %v", err)) 62 } 63 } 64 return l 65 } 66 67 // When debugging a particular http server-based test, 68 // this flag lets you run 69 // go test -run=BrokenTest -httptest.serve=127.0.0.1:8000 70 // to start the broken server so you can interact with it manually. 71 var serve = flag.String("httptest.serve", "", "if non-empty, httptest.NewServer serves on this address and blocks") 72 73 // NewServer starts and returns a new Server. 74 // The caller should call Close when finished, to shut it down. 75 func NewServer(handler http.Handler) *Server { 76 ts := NewUnstartedServer(handler) 77 ts.Start() 78 return ts 79 } 80 81 // NewUnstartedServer returns a new Server but doesn't start it. 82 // 83 // After changing its configuration, the caller should call Start or 84 // StartTLS. 85 // 86 // The caller should call Close when finished, to shut it down. 87 func NewUnstartedServer(handler http.Handler) *Server { 88 return &Server{ 89 Listener: newLocalListener(), 90 Config: &http.Server{Handler: handler}, 91 } 92 } 93 94 // Start starts a server from NewUnstartedServer. 95 func (s *Server) Start() { 96 if s.URL != "" { 97 panic("Server already started") 98 } 99 s.Listener = &historyListener{s.Listener, make([]net.Conn, 0)} 100 s.URL = "http://" + s.Listener.Addr().String() 101 s.wrapHandler() 102 go s.Config.Serve(s.Listener) 103 if *serve != "" { 104 fmt.Fprintln(os.Stderr, "httptest: serving on", s.URL) 105 select {} 106 } 107 } 108 109 // StartTLS starts TLS on a server from NewUnstartedServer. 110 func (s *Server) StartTLS() { 111 if s.URL != "" { 112 panic("Server already started") 113 } 114 cert, err := tls.X509KeyPair(localhostCert, localhostKey) 115 if err != nil { 116 panic(fmt.Sprintf("httptest: NewTLSServer: %v", err)) 117 } 118 119 s.TLS = &tls.Config{ 120 NextProtos: []string{"http/1.1"}, 121 Certificates: []tls.Certificate{cert}, 122 } 123 tlsListener := tls.NewListener(s.Listener, s.TLS) 124 125 s.Listener = &historyListener{tlsListener, make([]net.Conn, 0)} 126 s.URL = "https://" + s.Listener.Addr().String() 127 s.wrapHandler() 128 go s.Config.Serve(s.Listener) 129 } 130 131 func (s *Server) wrapHandler() { 132 h := s.Config.Handler 133 if h == nil { 134 h = http.DefaultServeMux 135 } 136 s.Config.Handler = &waitGroupHandler{ 137 s: s, 138 h: h, 139 } 140 } 141 142 // NewTLSServer starts and returns a new Server using TLS. 143 // The caller should call Close when finished, to shut it down. 144 func NewTLSServer(handler http.Handler) *Server { 145 ts := NewUnstartedServer(handler) 146 ts.StartTLS() 147 return ts 148 } 149 150 // Close shuts down the server and blocks until all outstanding 151 // requests on this server have completed. 152 func (s *Server) Close() { 153 s.Listener.Close() 154 s.wg.Wait() 155 } 156 157 // CloseClientConnections closes any currently open HTTP connections 158 // to the test Server. 159 func (s *Server) CloseClientConnections() { 160 hl, ok := s.Listener.(*historyListener) 161 if !ok { 162 return 163 } 164 for _, conn := range hl.history { 165 conn.Close() 166 } 167 } 168 169 // waitGroupHandler wraps a handler, incrementing and decrementing a 170 // sync.WaitGroup on each request, to enable Server.Close to block 171 // until outstanding requests are finished. 172 type waitGroupHandler struct { 173 s *Server 174 h http.Handler // non-nil 175 } 176 177 func (h *waitGroupHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 178 h.s.wg.Add(1) 179 defer h.s.wg.Done() // a defer, in case ServeHTTP below panics 180 h.h.ServeHTTP(w, r) 181 } 182 183 // localhostCert is a PEM-encoded TLS cert with SAN DNS names 184 // "127.0.0.1" and "[::1]", expiring at the last second of 2049 (the end 185 // of ASN.1 time). 186 var localhostCert = []byte(`-----BEGIN CERTIFICATE----- 187 MIIBOTCB5qADAgECAgEAMAsGCSqGSIb3DQEBBTAAMB4XDTcwMDEwMTAwMDAwMFoX 188 DTQ5MTIzMTIzNTk1OVowADBaMAsGCSqGSIb3DQEBAQNLADBIAkEAsuA5mAFMj6Q7 189 qoBzcvKzIq4kzuT5epSp2AkcQfyBHm7K13Ws7u+0b5Vb9gqTf5cAiIKcrtrXVqkL 190 8i1UQF6AzwIDAQABo08wTTAOBgNVHQ8BAf8EBAMCACQwDQYDVR0OBAYEBAECAwQw 191 DwYDVR0jBAgwBoAEAQIDBDAbBgNVHREEFDASggkxMjcuMC4wLjGCBVs6OjFdMAsG 192 CSqGSIb3DQEBBQNBAJH30zjLWRztrWpOCgJL8RQWLaKzhK79pVhAx6q/3NrF16C7 193 +l1BRZstTwIGdoGId8BRpErK1TXkniFb95ZMynM= 194 -----END CERTIFICATE----- 195 `) 196 197 // localhostKey is the private key for localhostCert. 198 var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY----- 199 MIIBPQIBAAJBALLgOZgBTI+kO6qAc3LysyKuJM7k+XqUqdgJHEH8gR5uytd1rO7v 200 tG+VW/YKk3+XAIiCnK7a11apC/ItVEBegM8CAwEAAQJBAI5sxq7naeR9ahyqRkJi 201 SIv2iMxLuPEHaezf5CYOPWjSjBPyVhyRevkhtqEjF/WkgL7C2nWpYHsUcBDBQVF0 202 3KECIQDtEGB2ulnkZAahl3WuJziXGLB+p8Wgx7wzSM6bHu1c6QIhAMEp++CaS+SJ 203 /TrU0zwY/fW4SvQeb49BPZUF3oqR8Xz3AiEA1rAJHBzBgdOQKdE3ksMUPcnvNJSN 204 poCcELmz2clVXtkCIQCLytuLV38XHToTipR4yMl6O+6arzAjZ56uq7m7ZRV0TwIh 205 AM65XAOw8Dsg9Kq78aYXiOEDc5DL0sbFUu/SlmRcCg93 206 -----END RSA PRIVATE KEY----- 207 `)