diff options
| author | Niklas Schnelle <niklas.schnelle@gmail.com> | 2017-03-13 07:43:16 +0530 |
|---|---|---|
| committer | Brad Fitzpatrick <bradfitz@golang.org> | 2017-06-08 17:45:27 +0000 |
| commit | 0b77d3eb009335aaa72205c6642409a5e4a408d6 (patch) | |
| tree | 5bd864887e6157d1c78fa92f934c7ad5de550725 /src/net/http/server.go | |
| parent | fab47f7b3a9d8ad91b96bf80f0b9dff2feda31d2 (diff) | |
| download | go-0b77d3eb009335aaa72205c6642409a5e4a408d6.tar.xz | |
net/http: add Server.ServeTLS method
Server.ServeTLS wraps Server.Serve with added TLS support. This is
particularly useful for serving on manually initialized listeners.
Example use-case includes ability to serve with TLS on listener
provided by systemd's socket activation.
A matching test heavily based on TestAutomaticHTTP2_ListenAndServe
is also included.
Original code by Gurpartap Singh as
https://go-review.googlesource.com/c/38114/
Fixes #13228
Change-Id: I73bb703f501574a84d261c2d7b9243a89fa52d62
Reviewed-on: https://go-review.googlesource.com/44074
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src/net/http/server.go')
| -rw-r--r-- | src/net/http/server.go | 92 |
1 files changed, 64 insertions, 28 deletions
diff --git a/src/net/http/server.go b/src/net/http/server.go index add05c24ed..c1b98daabf 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -2314,12 +2314,27 @@ func Serve(l net.Listener, handler Handler) error { return srv.Serve(l) } +// Serve accepts incoming HTTPS connections on the listener l, +// creating a new service goroutine for each. The service goroutines +// read requests and then call handler to reply to them. +// +// Handler is typically nil, in which case the DefaultServeMux is used. +// +// Additionally, files containing a certificate and matching private key +// for the server must be provided. If the certificate is signed by a +// certificate authority, the certFile should be the concatenation +// of the server's certificate, any intermediates, and the CA's certificate. +func ServeTLS(l net.Listener, handler Handler, certFile, keyFile string) error { + srv := &Server{Handler: handler} + return srv.ServeTLS(l, certFile, keyFile) +} + // A Server defines parameters for running an HTTP server. // The zero value for Server is a valid configuration. type Server struct { Addr string // TCP address to listen on, ":http" if empty Handler Handler // handler to invoke, http.DefaultServeMux if nil - TLSConfig *tls.Config // optional TLS config, used by ListenAndServeTLS + TLSConfig *tls.Config // optional TLS config, used by ServeTLS and ListenAndServeTLS // ReadTimeout is the maximum duration for reading the entire // request, including the body. @@ -2636,7 +2651,7 @@ func (srv *Server) shouldConfigureHTTP2ForServe() bool { return strSliceContains(srv.TLSConfig.NextProtos, http2NextProtoTLS) } -// ErrServerClosed is returned by the Server's Serve, ListenAndServe, +// ErrServerClosed is returned by the Server's Serve, ServeTLS, ListenAndServe, // and ListenAndServeTLS methods after a call to Shutdown or Close. var ErrServerClosed = errors.New("http: Server closed") @@ -2697,6 +2712,49 @@ func (srv *Server) Serve(l net.Listener) error { } } +// ServeTLS accepts incoming connections on the Listener l, creating a +// new service goroutine for each. The service goroutines read requests and +// then call srv.Handler to reply to them. +// +// Additionally, files containing a certificate and matching private key for +// the server must be provided if neither the Server's TLSConfig.Certificates +// nor TLSConfig.GetCertificate are populated.. If the certificate is signed by +// a certificate authority, the certFile should be the concatenation of the +// server's certificate, any intermediates, and the CA's certificate. +// +// For HTTP/2 support, srv.TLSConfig should be initialized to the +// provided listener's TLS Config before calling Serve. If +// srv.TLSConfig is non-nil and doesn't include the string "h2" in +// Config.NextProtos, HTTP/2 support is not enabled. +// +// ServeTLS always returns a non-nil error. After Shutdown or Close, the +// returned error is ErrServerClosed. +func (srv *Server) ServeTLS(l net.Listener, certFile, keyFile string) error { + // Setup HTTP/2 before srv.Serve, to initialize srv.TLSConfig + // before we clone it and create the TLS Listener. + if err := srv.setupHTTP2_ServeTLS(); err != nil { + return err + } + + config := cloneTLSConfig(srv.TLSConfig) + if !strSliceContains(config.NextProtos, "http/1.1") { + config.NextProtos = append(config.NextProtos, "http/1.1") + } + + configHasCert := len(config.Certificates) > 0 || config.GetCertificate != nil + if !configHasCert || certFile != "" || keyFile != "" { + var err error + config.Certificates = make([]tls.Certificate, 1) + config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile) + if err != nil { + return err + } + } + + tlsListener := tls.NewListener(l, config) + return srv.Serve(tlsListener) +} + func (s *Server) trackListener(ln net.Listener, add bool) { s.mu.Lock() defer s.mu.Unlock() @@ -2868,47 +2926,25 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error { addr = ":https" } - // Setup HTTP/2 before srv.Serve, to initialize srv.TLSConfig - // before we clone it and create the TLS Listener. - if err := srv.setupHTTP2_ListenAndServeTLS(); err != nil { - return err - } - - config := cloneTLSConfig(srv.TLSConfig) - if !strSliceContains(config.NextProtos, "http/1.1") { - config.NextProtos = append(config.NextProtos, "http/1.1") - } - - configHasCert := len(config.Certificates) > 0 || config.GetCertificate != nil - if !configHasCert || certFile != "" || keyFile != "" { - var err error - config.Certificates = make([]tls.Certificate, 1) - config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile) - if err != nil { - return err - } - } - ln, err := net.Listen("tcp", addr) if err != nil { return err } - tlsListener := tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, config) - return srv.Serve(tlsListener) + return srv.ServeTLS(tcpKeepAliveListener{ln.(*net.TCPListener)}, certFile, keyFile) } -// setupHTTP2_ListenAndServeTLS conditionally configures HTTP/2 on +// setupHTTP2_ServeTLS conditionally configures HTTP/2 on // srv and returns whether there was an error setting it up. If it is // not configured for policy reasons, nil is returned. -func (srv *Server) setupHTTP2_ListenAndServeTLS() error { +func (srv *Server) setupHTTP2_ServeTLS() error { srv.nextProtoOnce.Do(srv.onceSetNextProtoDefaults) return srv.nextProtoErr } // setupHTTP2_Serve is called from (*Server).Serve and conditionally // configures HTTP/2 on srv using a more conservative policy than -// setupHTTP2_ListenAndServeTLS because Serve may be called +// setupHTTP2_ServeTLS because Serve may be called // concurrently. // // The tests named TestTransportAutomaticHTTP2* and |
