github.com/d4l3k/go@v0.0.0-20151015000803-65fc379daeda/src/net/http/httptest/server.go (about)

     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  
    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/crypto/tls:
   207  // go run generate_cert.go  --rsa-bits 1024 --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  MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zANBgkqhkiG9w0BAQsFADAS
   210  MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
   211  MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
   212  iQKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9SjY1bIw4
   213  iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZBl2+XsDul
   214  rKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQABo2gwZjAO
   215  BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw
   216  AwEB/zAuBgNVHREEJzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAA
   217  AAAAATANBgkqhkiG9w0BAQsFAAOBgQCEcetwO59EWk7WiJsG4x8SY+UIAA+flUI9
   218  tyC4lNhbcF2Idq9greZwbYCqTTTr2XiRNSMLCOjKyI7ukPoPjo16ocHj+P3vZGfs
   219  h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM
   220  fblo6RBxUQ==
   221  -----END CERTIFICATE-----`)
   222  
   223  // localhostKey is the private key for localhostCert.
   224  var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
   225  MIICXgIBAAKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9
   226  SjY1bIw4iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZB
   227  l2+XsDulrKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQAB
   228  AoGAGRzwwir7XvBOAy5tM/uV6e+Zf6anZzus1s1Y1ClbjbE6HXbnWWF/wbZGOpet
   229  3Zm4vD6MXc7jpTLryzTQIvVdfQbRc6+MUVeLKwZatTXtdZrhu+Jk7hx0nTPy8Jcb
   230  uJqFk541aEw+mMogY/xEcfbWd6IOkp+4xqjlFLBEDytgbIECQQDvH/E6nk+hgN4H
   231  qzzVtxxr397vWrjrIgPbJpQvBsafG7b0dA4AFjwVbFLmQcj2PprIMmPcQrooz8vp
   232  jy4SHEg1AkEA/v13/5M47K9vCxmb8QeD/asydfsgS5TeuNi8DoUBEmiSJwma7FXY
   233  fFUtxuvL7XvjwjN5B30pNEbc6Iuyt7y4MQJBAIt21su4b3sjXNueLKH85Q+phy2U
   234  fQtuUE9txblTu14q3N7gHRZB4ZMhFYyDy8CKrN2cPg/Fvyt0Xlp/DoCzjA0CQQDU
   235  y2ptGsuSmgUtWj3NM9xuwYPm+Z/F84K6+ARYiZ6PYj013sovGKUFfYAqVXVlxtIX
   236  qyUBnu3X9ps8ZfjLZO7BAkEAlT4R5Yl6cGhaJQYZHOde3JEMhNRcVFMO8dJDaFeo
   237  f9Oeos0UUothgiDktdQHxdNEwLjQf7lJJBzV+5OtwswCWA==
   238  -----END RSA PRIVATE KEY-----`)