From 84d2482ddbff9564c9ad75b2d30af66e3ddfd44d Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Thu, 12 May 2016 15:08:58 -0400 Subject: Updating go depencancies. Switching to go1.6 vendoring (#2949) --- vendor/github.com/braintree/manners/LICENSE | 19 ++ vendor/github.com/braintree/manners/README.md | 36 +++ vendor/github.com/braintree/manners/interfaces.go | 7 + vendor/github.com/braintree/manners/server.go | 292 ++++++++++++++++++++++ vendor/github.com/braintree/manners/static.go | 47 ++++ 5 files changed, 401 insertions(+) create mode 100644 vendor/github.com/braintree/manners/LICENSE create mode 100644 vendor/github.com/braintree/manners/README.md create mode 100644 vendor/github.com/braintree/manners/interfaces.go create mode 100644 vendor/github.com/braintree/manners/server.go create mode 100644 vendor/github.com/braintree/manners/static.go (limited to 'vendor/github.com/braintree') diff --git a/vendor/github.com/braintree/manners/LICENSE b/vendor/github.com/braintree/manners/LICENSE new file mode 100644 index 000000000..91ef5beed --- /dev/null +++ b/vendor/github.com/braintree/manners/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2014 Braintree, a division of PayPal, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/braintree/manners/README.md b/vendor/github.com/braintree/manners/README.md new file mode 100644 index 000000000..09f6f9693 --- /dev/null +++ b/vendor/github.com/braintree/manners/README.md @@ -0,0 +1,36 @@ +# Manners + +A *polite* webserver for Go. + +Manners allows you to shut your Go webserver down gracefully, without dropping any requests. It can act as a drop-in replacement for the standard library's http.ListenAndServe function: + +```go +func main() { + handler := MyHTTPHandler() + manners.ListenAndServe(":7000", handler) +} +``` + +Then, when you want to shut the server down: + +```go +manners.Close() +``` + +(Note that this does not block until all the requests are finished. Rather, the call to manners.ListenAndServe will stop blocking when all the requests are finished.) + +Manners ensures that all requests are served by incrementing a WaitGroup when a request comes in and decrementing it when the request finishes. + +If your request handler spawns Goroutines that are not guaranteed to finish with the request, you can ensure they are also completed with the `StartRoutine` and `FinishRoutine` functions on the server. + +### Known Issues + +Manners does not correctly shut down long-lived keepalive connections when issued a shutdown command. Clients on an idle keepalive connection may see a connection reset error rather than a close. See https://github.com/braintree/manners/issues/13 for details. + +### Compatability + +Manners 0.3.0 and above uses standard library functionality introduced in Go 1.3. + +### Installation + +`go get github.com/braintree/manners` diff --git a/vendor/github.com/braintree/manners/interfaces.go b/vendor/github.com/braintree/manners/interfaces.go new file mode 100644 index 000000000..fd0732857 --- /dev/null +++ b/vendor/github.com/braintree/manners/interfaces.go @@ -0,0 +1,7 @@ +package manners + +type waitGroup interface { + Add(int) + Done() + Wait() +} diff --git a/vendor/github.com/braintree/manners/server.go b/vendor/github.com/braintree/manners/server.go new file mode 100644 index 000000000..dfd3b873b --- /dev/null +++ b/vendor/github.com/braintree/manners/server.go @@ -0,0 +1,292 @@ +/* +Package manners provides a wrapper for a standard net/http server that +ensures all active HTTP client have completed their current request +before the server shuts down. + +It can be used a drop-in replacement for the standard http package, +or can wrap a pre-configured Server. + +eg. + + http.Handle("/hello", func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("Hello\n")) + }) + + log.Fatal(manners.ListenAndServe(":8080", nil)) + +or for a customized server: + + s := manners.NewWithServer(&http.Server{ + Addr: ":8080", + Handler: myHandler, + ReadTimeout: 10 * time.Second, + WriteTimeout: 10 * time.Second, + MaxHeaderBytes: 1 << 20, + }) + log.Fatal(s.ListenAndServe()) + +The server will shut down cleanly when the Close() method is called: + + go func() { + sigchan := make(chan os.Signal, 1) + signal.Notify(sigchan, os.Interrupt, os.Kill) + <-sigchan + log.Info("Shutting down...") + manners.Close() + }() + + http.Handle("/hello", myHandler) + log.Fatal(manners.ListenAndServe(":8080", nil)) +*/ +package manners + +import ( + "crypto/tls" + "net" + "net/http" + "sync" + "sync/atomic" +) + +// A GracefulServer maintains a WaitGroup that counts how many in-flight +// requests the server is handling. When it receives a shutdown signal, +// it stops accepting new requests but does not actually shut down until +// all in-flight requests terminate. +// +// GracefulServer embeds the underlying net/http.Server making its non-override +// methods and properties avaiable. +// +// It must be initialized by calling NewWithServer. +type GracefulServer struct { + *http.Server + + shutdown chan bool + shutdownFinished chan bool + wg waitGroup + routinesCount int + + lcsmu sync.RWMutex + connections map[net.Conn]bool + + up chan net.Listener // Only used by test code. +} + +// NewServer creates a new GracefulServer. +func NewServer() *GracefulServer { + return NewWithServer(new(http.Server)) +} + +// NewWithServer wraps an existing http.Server object and returns a +// GracefulServer that supports all of the original Server operations. +func NewWithServer(s *http.Server) *GracefulServer { + return &GracefulServer{ + Server: s, + shutdown: make(chan bool), + shutdownFinished: make(chan bool, 1), + wg: new(sync.WaitGroup), + routinesCount: 0, + connections: make(map[net.Conn]bool), + } +} + +// Close stops the server from accepting new requets and begins shutting down. +// It returns true if it's the first time Close is called. +func (s *GracefulServer) Close() bool { + return <-s.shutdown +} + +// BlockingClose is similar to Close, except that it blocks until the last +// connection has been closed. +func (s *GracefulServer) BlockingClose() bool { + result := s.Close() + <-s.shutdownFinished + return result +} + +// ListenAndServe provides a graceful equivalent of net/http.Serve.ListenAndServe. +func (s *GracefulServer) ListenAndServe() error { + addr := s.Addr + if addr == "" { + addr = ":http" + } + listener, err := net.Listen("tcp", addr) + if err != nil { + return err + } + + return s.Serve(listener) +} + +// ListenAndServeTLS provides a graceful equivalent of net/http.Serve.ListenAndServeTLS. +func (s *GracefulServer) ListenAndServeTLS(certFile, keyFile string) error { + // direct lift from net/http/server.go + addr := s.Addr + if addr == "" { + addr = ":https" + } + config := &tls.Config{} + if s.TLSConfig != nil { + *config = *s.TLSConfig + } + if config.NextProtos == nil { + config.NextProtos = []string{"http/1.1"} + } + + 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 + } + + return s.Serve(tls.NewListener(ln, config)) +} + +// Serve provides a graceful equivalent net/http.Server.Serve. +func (s *GracefulServer) Serve(listener net.Listener) error { + // Wrap the server HTTP handler into graceful one, that will close kept + // alive connections if a new request is received after shutdown. + gracefulHandler := newGracefulHandler(s.Server.Handler) + s.Server.Handler = gracefulHandler + + // Start a goroutine that waits for a shutdown signal and will stop the + // listener when it receives the signal. That in turn will result in + // unblocking of the http.Serve call. + go func() { + s.shutdown <- true + close(s.shutdown) + gracefulHandler.Close() + s.Server.SetKeepAlivesEnabled(false) + listener.Close() + }() + + originalConnState := s.Server.ConnState + + // s.ConnState is invoked by the net/http.Server every time a connection + // changes state. It keeps track of each connection's state over time, + // enabling manners to handle persisted connections correctly. + s.ConnState = func(conn net.Conn, newState http.ConnState) { + s.lcsmu.RLock() + protected := s.connections[conn] + s.lcsmu.RUnlock() + + switch newState { + + case http.StateNew: + // New connection -> StateNew + protected = true + s.StartRoutine() + + case http.StateActive: + // (StateNew, StateIdle) -> StateActive + if gracefulHandler.IsClosed() { + conn.Close() + break + } + + if !protected { + protected = true + s.StartRoutine() + } + + default: + // (StateNew, StateActive) -> (StateIdle, StateClosed, StateHiJacked) + if protected { + s.FinishRoutine() + protected = false + } + } + + s.lcsmu.Lock() + if newState == http.StateClosed || newState == http.StateHijacked { + delete(s.connections, conn) + } else { + s.connections[conn] = protected + } + s.lcsmu.Unlock() + + if originalConnState != nil { + originalConnState(conn, newState) + } + } + + // A hook to allow the server to notify others when it is ready to receive + // requests; only used by tests. + if s.up != nil { + s.up <- listener + } + + err := s.Server.Serve(listener) + // An error returned on shutdown is not worth reporting. + if err != nil && gracefulHandler.IsClosed() { + err = nil + } + + // Wait for pending requests to complete regardless the Serve result. + s.wg.Wait() + s.shutdownFinished <- true + return err +} + +// StartRoutine increments the server's WaitGroup. Use this if a web request +// starts more goroutines and these goroutines are not guaranteed to finish +// before the request. +func (s *GracefulServer) StartRoutine() { + s.lcsmu.Lock() + defer s.lcsmu.Unlock() + s.wg.Add(1) + s.routinesCount++ +} + +// FinishRoutine decrements the server's WaitGroup. Use this to complement +// StartRoutine(). +func (s *GracefulServer) FinishRoutine() { + s.lcsmu.Lock() + defer s.lcsmu.Unlock() + s.wg.Done() + s.routinesCount-- +} + +// RoutinesCount returns the number of currently running routines +func (s *GracefulServer) RoutinesCount() int { + s.lcsmu.RLock() + defer s.lcsmu.RUnlock() + return s.routinesCount +} + +// gracefulHandler is used by GracefulServer to prevent calling ServeHTTP on +// to be closed kept-alive connections during the server shutdown. +type gracefulHandler struct { + closed int32 // accessed atomically. + wrapped http.Handler +} + +func newGracefulHandler(wrapped http.Handler) *gracefulHandler { + return &gracefulHandler{ + wrapped: wrapped, + } +} + +func (gh *gracefulHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if atomic.LoadInt32(&gh.closed) == 0 { + gh.wrapped.ServeHTTP(w, r) + return + } + r.Body.Close() + // Server is shutting down at this moment, and the connection that this + // handler is being called on is about to be closed. So we do not need to + // actually execute the handler logic. +} + +func (gh *gracefulHandler) Close() { + atomic.StoreInt32(&gh.closed, 1) +} + +func (gh *gracefulHandler) IsClosed() bool { + return atomic.LoadInt32(&gh.closed) == 1 +} diff --git a/vendor/github.com/braintree/manners/static.go b/vendor/github.com/braintree/manners/static.go new file mode 100644 index 000000000..b53950675 --- /dev/null +++ b/vendor/github.com/braintree/manners/static.go @@ -0,0 +1,47 @@ +package manners + +import ( + "net" + "net/http" + "sync" +) + +var ( + defaultServer *GracefulServer + defaultServerLock = &sync.Mutex{} +) + +func init() { + defaultServerLock.Lock() +} + +// ListenAndServe provides a graceful version of the function provided by the +// net/http package. Call Close() to stop the server. +func ListenAndServe(addr string, handler http.Handler) error { + defaultServer = NewWithServer(&http.Server{Addr: addr, Handler: handler}) + defaultServerLock.Unlock() + return defaultServer.ListenAndServe() +} + +// ListenAndServeTLS provides a graceful version of the function provided by the +// net/http package. Call Close() to stop the server. +func ListenAndServeTLS(addr string, certFile string, keyFile string, handler http.Handler) error { + defaultServer = NewWithServer(&http.Server{Addr: addr, Handler: handler}) + defaultServerLock.Unlock() + return defaultServer.ListenAndServeTLS(certFile, keyFile) +} + +// Serve provides a graceful version of the function provided by the net/http +// package. Call Close() to stop the server. +func Serve(l net.Listener, handler http.Handler) error { + defaultServer = NewWithServer(&http.Server{Handler: handler}) + defaultServerLock.Unlock() + return defaultServer.Serve(l) +} + +// Shuts down the default server used by ListenAndServe, ListenAndServeTLS and +// Serve. It returns true if it's the first time Close is called. +func Close() bool { + defaultServerLock.Lock() + return defaultServer.Close() +} -- cgit v1.2.3-1-g7c22