libgo, compiler: Upgrade libgo to Go 1.4, except for runtime.
[official-gcc.git] / libgo / go / net / http / httptest / server.go
blob789e7bf41e668dc9a60e589fdd9973e0a1264d5f
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
7 package httptest
9 import (
10 "crypto/tls"
11 "flag"
12 "fmt"
13 "net"
14 "net/http"
15 "os"
16 "sync"
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
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.
28 TLS *tls.Config
30 // Config may be changed after calling NewUnstartedServer and
31 // before Start or StartTLS.
32 Config *http.Server
34 // wg counts the number of outstanding HTTP requests on this server.
35 // Close blocks until all requests are finished.
36 wg sync.WaitGroup
39 // historyListener keeps track of all connections that it's ever
40 // accepted.
41 type historyListener struct {
42 net.Listener
43 sync.Mutex // protects history
44 history []net.Conn
47 func (hs *historyListener) Accept() (c net.Conn, err error) {
48 c, err = hs.Listener.Accept()
49 if err == nil {
50 hs.Lock()
51 hs.history = append(hs.history, c)
52 hs.Unlock()
54 return
57 func newLocalListener() net.Listener {
58 if *serve != "" {
59 l, err := net.Listen("tcp", *serve)
60 if err != nil {
61 panic(fmt.Sprintf("httptest: failed to listen on %v: %v", *serve, err))
63 return l
65 l, err := net.Listen("tcp", "127.0.0.1:0")
66 if err != nil {
67 if l, err = net.Listen("tcp6", "[::1]:0"); err != nil {
68 panic(fmt.Sprintf("httptest: failed to listen on a port: %v", err))
71 return l
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)
84 ts.Start()
85 return ts
88 // NewUnstartedServer returns a new Server but doesn't start it.
90 // After changing its configuration, the caller should call Start or
91 // StartTLS.
93 // The caller should call Close when finished, to shut it down.
94 func NewUnstartedServer(handler http.Handler) *Server {
95 return &Server{
96 Listener: newLocalListener(),
97 Config: &http.Server{Handler: handler},
101 // Start starts a server from NewUnstartedServer.
102 func (s *Server) Start() {
103 if s.URL != "" {
104 panic("Server already started")
106 s.Listener = &historyListener{Listener: s.Listener}
107 s.URL = "http://" + s.Listener.Addr().String()
108 s.wrapHandler()
109 go s.Config.Serve(s.Listener)
110 if *serve != "" {
111 fmt.Fprintln(os.Stderr, "httptest: serving on", s.URL)
112 select {}
116 // StartTLS starts TLS on a server from NewUnstartedServer.
117 func (s *Server) StartTLS() {
118 if s.URL != "" {
119 panic("Server already started")
121 cert, err := tls.X509KeyPair(localhostCert, localhostKey)
122 if err != nil {
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()
141 s.wrapHandler()
142 go s.Config.Serve(s.Listener)
145 func (s *Server) wrapHandler() {
146 h := s.Config.Handler
147 if h == nil {
148 h = http.DefaultServeMux
150 s.Config.Handler = &waitGroupHandler{
151 s: s,
152 h: h,
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)
160 ts.StartTLS()
161 return ts
164 // Close shuts down the server and blocks until all outstanding
165 // requests on this server have completed.
166 func (s *Server) Close() {
167 s.Listener.Close()
168 s.wg.Wait()
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)
179 if !ok {
180 return
182 hl.Lock()
183 for _, conn := range hl.history {
184 conn.Close()
186 hl.Unlock()
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 {
193 s *Server
194 h http.Handler // non-nil
197 func (h *waitGroupHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
198 h.s.wg.Add(1)
199 defer h.s.wg.Done() // a defer, in case ServeHTTP below panics
200 h.h.ServeHTTP(w, r)
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
205 // of ASN.1 time).
206 // generated from src/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-----`)