~chipaca/ubuntu-push/gsettings

« back to all changes in this revision

Viewing changes to http13client/httptest/server.go

  • Committer: Samuele Pedroni (Canonical Services Ltd.)
  • Date: 2014-03-19 20:20:19 UTC
  • mto: This revision was merged to the branch mainline in revision 82.
  • Revision ID: samuele.pedroni@canonical.com-20140319202019-p0w8krshj1098f82
grab go 1.3 dev net/http and massage it so that the test run on 1.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
        "launchpad.net/ubuntu-push/http13client"
 
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
 
 
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
 
29
 
 
30
        // Config may be changed after calling NewUnstartedServer and
 
31
        // before Start or StartTLS.
 
32
        Config *http.Server
 
33
 
 
34
        // wg counts the number of outstanding HTTP requests on this server.
 
35
        // Close blocks until all requests are finished.
 
36
        wg sync.WaitGroup
 
37
}
 
38
 
 
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
 
45
}
 
46
 
 
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()
 
53
        }
 
54
        return
 
55
}
 
56
 
 
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))
 
62
                }
 
63
                return l
 
64
        }
 
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))
 
69
                }
 
70
        }
 
71
        return l
 
72
}
 
73
 
 
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")
 
79
 
 
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
 
86
}
 
87
 
 
88
// NewUnstartedServer returns a new Server but doesn't start it.
 
89
//
 
90
// After changing its configuration, the caller should call Start or
 
91
// StartTLS.
 
92
//
 
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},
 
98
        }
 
99
}
 
100
 
 
101
// Start starts a server from NewUnstartedServer.
 
102
func (s *Server) Start() {
 
103
        if s.URL != "" {
 
104
                panic("Server already started")
 
105
        }
 
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 {}
 
113
        }
 
114
}
 
115
 
 
116
// StartTLS starts TLS on a server from NewUnstartedServer.
 
117
func (s *Server) StartTLS() {
 
118
        if s.URL != "" {
 
119
                panic("Server already started")
 
120
        }
 
121
        cert, err := tls.X509KeyPair(localhostCert, localhostKey)
 
122
        if err != nil {
 
123
                panic(fmt.Sprintf("httptest: NewTLSServer: %v", err))
 
124
        }
 
125
 
 
126
        existingConfig := s.TLS
 
127
        s.TLS = new(tls.Config)
 
128
        if existingConfig != nil {
 
129
                *s.TLS = *existingConfig
 
130
        }
 
131
        if s.TLS.NextProtos == nil {
 
132
                s.TLS.NextProtos = []string{"http/1.1"}
 
133
        }
 
134
        if len(s.TLS.Certificates) == 0 {
 
135
                s.TLS.Certificates = []tls.Certificate{cert}
 
136
        }
 
137
        tlsListener := tls.NewListener(s.Listener, s.TLS)
 
138
 
 
139
        s.Listener = &historyListener{Listener: tlsListener}
 
140
        s.URL = "https://" + s.Listener.Addr().String()
 
141
        s.wrapHandler()
 
142
        go s.Config.Serve(s.Listener)
 
143
}
 
144
 
 
145
func (s *Server) wrapHandler() {
 
146
        h := s.Config.Handler
 
147
        if h == nil {
 
148
                h = http.DefaultServeMux
 
149
        }
 
150
        s.Config.Handler = &waitGroupHandler{
 
151
                s: s,
 
152
                h: h,
 
153
        }
 
154
}
 
155
 
 
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
 
162
}
 
163
 
 
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()
 
172
        }
 
173
}
 
174
 
 
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
 
181
        }
 
182
        hl.Lock()
 
183
        for _, conn := range hl.history {
 
184
                conn.Close()
 
185
        }
 
186
        hl.Unlock()
 
187
}
 
188
 
 
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
 
195
}
 
196
 
 
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)
 
201
}
 
202
 
 
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/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-----`)
 
218
 
 
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-----`)