Vendor main dependencies.
This commit is contained in:
parent
49a09ab7dd
commit
dd5e3fba01
2738 changed files with 1045689 additions and 0 deletions
19
vendor/github.com/mailgun/manners/LICENSE
generated
vendored
Normal file
19
vendor/github.com/mailgun/manners/LICENSE
generated
vendored
Normal file
|
@ -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.
|
7
vendor/github.com/mailgun/manners/interfaces.go
generated
vendored
Normal file
7
vendor/github.com/mailgun/manners/interfaces.go
generated
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
package manners
|
||||
|
||||
type waitGroup interface {
|
||||
Add(int)
|
||||
Done()
|
||||
Wait()
|
||||
}
|
155
vendor/github.com/mailgun/manners/listener.go
generated
vendored
Normal file
155
vendor/github.com/mailgun/manners/listener.go
generated
vendored
Normal file
|
@ -0,0 +1,155 @@
|
|||
package manners
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// NewListener wraps an existing listener for use with
|
||||
// GracefulServer.
|
||||
//
|
||||
// Note that you generally don't need to use this directly as
|
||||
// GracefulServer will automatically wrap any non-graceful listeners
|
||||
// supplied to it.
|
||||
func NewListener(l net.Listener) *GracefulListener {
|
||||
return &GracefulListener{
|
||||
listener: l,
|
||||
mutex: &sync.RWMutex{},
|
||||
open: true,
|
||||
}
|
||||
}
|
||||
|
||||
// A GracefulListener differs from a standard net.Listener in one way: if
|
||||
// Accept() is called after it is gracefully closed, it returns a
|
||||
// listenerAlreadyClosed error. The GracefulServer will ignore this error.
|
||||
type GracefulListener struct {
|
||||
listener net.Listener
|
||||
open bool
|
||||
mutex *sync.RWMutex
|
||||
}
|
||||
|
||||
func (l *GracefulListener) isClosed() bool {
|
||||
l.mutex.RLock()
|
||||
defer l.mutex.RUnlock()
|
||||
return !l.open
|
||||
}
|
||||
|
||||
func (l *GracefulListener) Addr() net.Addr {
|
||||
return l.listener.Addr()
|
||||
}
|
||||
|
||||
// Accept implements the Accept method in the Listener interface.
|
||||
func (l *GracefulListener) Accept() (net.Conn, error) {
|
||||
conn, err := l.listener.Accept()
|
||||
if err != nil {
|
||||
if l.isClosed() {
|
||||
err = fmt.Errorf("listener already closed: err=(%s)", err)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
// Close tells the wrapped listener to stop listening. It is idempotent.
|
||||
func (l *GracefulListener) Close() error {
|
||||
l.mutex.Lock()
|
||||
defer l.mutex.Unlock()
|
||||
if !l.open {
|
||||
return nil
|
||||
}
|
||||
l.open = false
|
||||
return l.listener.Close()
|
||||
}
|
||||
|
||||
func (l *GracefulListener) GetFile() (*os.File, error) {
|
||||
return getListenerFile(l.listener)
|
||||
}
|
||||
|
||||
func (l *GracefulListener) Clone() (net.Listener, error) {
|
||||
l.mutex.Lock()
|
||||
defer l.mutex.Unlock()
|
||||
|
||||
if !l.open {
|
||||
return nil, errors.New("listener is already closed")
|
||||
}
|
||||
|
||||
file, err := l.GetFile()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
fl, err := net.FileListener(file)
|
||||
if nil != err {
|
||||
return nil, err
|
||||
}
|
||||
return fl, nil
|
||||
}
|
||||
|
||||
// A listener implements a network listener (net.Listener) for TLS connections.
|
||||
// direct lift from crypto/tls.go
|
||||
type TLSListener struct {
|
||||
net.Listener
|
||||
config *tls.Config
|
||||
}
|
||||
|
||||
// Accept waits for and returns the next incoming TLS connection.
|
||||
// The returned connection c is a *tls.Conn.
|
||||
func (l *TLSListener) Accept() (c net.Conn, err error) {
|
||||
c, err = l.Listener.Accept()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c = tls.Server(c, l.config)
|
||||
return
|
||||
}
|
||||
|
||||
// NewListener creates a Listener which accepts connections from an inner
|
||||
// Listener and wraps each connection with Server.
|
||||
// The configuration config must be non-nil and must have
|
||||
// at least one certificate.
|
||||
func NewTLSListener(inner net.Listener, config *tls.Config) net.Listener {
|
||||
l := new(TLSListener)
|
||||
l.Listener = inner
|
||||
l.config = config
|
||||
return l
|
||||
}
|
||||
|
||||
// TCPKeepAliveListener sets TCP keep-alive timeouts on accepted
|
||||
// connections. It's used by ListenAndServe and ListenAndServeTLS so
|
||||
// dead TCP connections (e.g. closing laptop mid-download) eventually
|
||||
// go away.
|
||||
//
|
||||
// direct lift from net/http/server.go
|
||||
type TCPKeepAliveListener struct {
|
||||
*net.TCPListener
|
||||
}
|
||||
|
||||
func (ln TCPKeepAliveListener) Accept() (c net.Conn, err error) {
|
||||
tc, err := ln.AcceptTCP()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
tc.SetKeepAlive(true)
|
||||
tc.SetKeepAlivePeriod(3 * time.Minute)
|
||||
return tc, nil
|
||||
}
|
||||
|
||||
func getListenerFile(listener net.Listener) (*os.File, error) {
|
||||
switch t := listener.(type) {
|
||||
case *net.TCPListener:
|
||||
return t.File()
|
||||
case *net.UnixListener:
|
||||
return t.File()
|
||||
case TCPKeepAliveListener:
|
||||
return t.TCPListener.File()
|
||||
case *TLSListener:
|
||||
return getListenerFile(t.Listener)
|
||||
}
|
||||
return nil, fmt.Errorf("Unsupported listener: %T", listener)
|
||||
}
|
379
vendor/github.com/mailgun/manners/server.go
generated
vendored
Normal file
379
vendor/github.com/mailgun/manners/server.go
generated
vendored
Normal file
|
@ -0,0 +1,379 @@
|
|||
/*
|
||||
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"
|
||||
"os"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// StateHandler can be called by the server if the state of the connection changes.
|
||||
// Notice that it passed previous state and the new state as parameters.
|
||||
type StateHandler func(net.Conn, http.ConnState, http.ConnState)
|
||||
|
||||
// Options used by NewWithOptions to provide parameters for a GracefulServer
|
||||
// instance to be created.
|
||||
type Options struct {
|
||||
Server *http.Server
|
||||
StateHandler StateHandler
|
||||
Listener net.Listener
|
||||
}
|
||||
|
||||
// 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 NewServer or NewWithServer
|
||||
type GracefulServer struct {
|
||||
*http.Server
|
||||
shutdown chan bool
|
||||
shutdownFinished chan bool
|
||||
wg waitGroup
|
||||
routinesCount int32
|
||||
listener *GracefulListener
|
||||
stateHandler StateHandler
|
||||
connToProps map[net.Conn]connProperties
|
||||
connToPropsMtx sync.RWMutex
|
||||
|
||||
up chan net.Listener // Only used by test code.
|
||||
}
|
||||
|
||||
// NewServer creates a new GracefulServer.
|
||||
func NewServer() *GracefulServer {
|
||||
return NewWithOptions(Options{})
|
||||
}
|
||||
|
||||
// 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 NewWithOptions(Options{Server: s})
|
||||
}
|
||||
|
||||
// NewWithOptions creates a GracefulServer instance with the specified options.
|
||||
func NewWithOptions(o Options) *GracefulServer {
|
||||
var listener *GracefulListener
|
||||
if o.Listener != nil {
|
||||
g, ok := o.Listener.(*GracefulListener)
|
||||
if !ok {
|
||||
listener = NewListener(o.Listener)
|
||||
} else {
|
||||
listener = g
|
||||
}
|
||||
}
|
||||
if o.Server == nil {
|
||||
o.Server = new(http.Server)
|
||||
}
|
||||
return &GracefulServer{
|
||||
Server: o.Server,
|
||||
listener: listener,
|
||||
stateHandler: o.StateHandler,
|
||||
shutdown: make(chan bool),
|
||||
shutdownFinished: make(chan bool, 1),
|
||||
wg: new(sync.WaitGroup),
|
||||
connToProps: make(map[net.Conn]connProperties),
|
||||
}
|
||||
}
|
||||
|
||||
// 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 (gs *GracefulServer) Close() bool {
|
||||
return <-gs.shutdown
|
||||
}
|
||||
|
||||
// BlockingClose is similar to Close, except that it blocks until the last
|
||||
// connection has been closed.
|
||||
func (gs *GracefulServer) BlockingClose() bool {
|
||||
result := gs.Close()
|
||||
<-gs.shutdownFinished
|
||||
return result
|
||||
}
|
||||
|
||||
// ListenAndServe provides a graceful equivalent of net/http.Serve.ListenAndServe.
|
||||
func (gs *GracefulServer) ListenAndServe() error {
|
||||
if gs.listener == nil {
|
||||
oldListener, err := net.Listen("tcp", gs.Addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
gs.listener = NewListener(oldListener.(*net.TCPListener))
|
||||
}
|
||||
return gs.Serve(gs.listener)
|
||||
}
|
||||
|
||||
// ListenAndServeTLS provides a graceful equivalent of net/http.Serve.ListenAndServeTLS.
|
||||
func (gs *GracefulServer) ListenAndServeTLS(certFile, keyFile string) error {
|
||||
// direct lift from net/http/server.go
|
||||
addr := gs.Addr
|
||||
if addr == "" {
|
||||
addr = ":https"
|
||||
}
|
||||
config := &tls.Config{}
|
||||
if gs.TLSConfig != nil {
|
||||
*config = *gs.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
|
||||
}
|
||||
|
||||
return gs.ListenAndServeTLSWithConfig(config)
|
||||
}
|
||||
|
||||
// ListenAndServeTLS provides a graceful equivalent of net/http.Serve.ListenAndServeTLS.
|
||||
func (gs *GracefulServer) ListenAndServeTLSWithConfig(config *tls.Config) error {
|
||||
addr := gs.Addr
|
||||
if addr == "" {
|
||||
addr = ":https"
|
||||
}
|
||||
|
||||
if gs.listener == nil {
|
||||
ln, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tlsListener := NewTLSListener(TCPKeepAliveListener{ln.(*net.TCPListener)}, config)
|
||||
gs.listener = NewListener(tlsListener)
|
||||
}
|
||||
return gs.Serve(gs.listener)
|
||||
}
|
||||
|
||||
func (gs *GracefulServer) GetFile() (*os.File, error) {
|
||||
return gs.listener.GetFile()
|
||||
}
|
||||
|
||||
func (gs *GracefulServer) HijackListener(s *http.Server, config *tls.Config) (*GracefulServer, error) {
|
||||
listenerUnsafePtr := unsafe.Pointer(gs.listener)
|
||||
listener, err := (*GracefulListener)(atomic.LoadPointer(&listenerUnsafePtr)).Clone()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if config != nil {
|
||||
listener = NewTLSListener(TCPKeepAliveListener{listener.(*net.TCPListener)}, config)
|
||||
}
|
||||
|
||||
other := NewWithServer(s)
|
||||
other.listener = NewListener(listener)
|
||||
return other, nil
|
||||
}
|
||||
|
||||
// Serve provides a graceful equivalent net/http.Server.Serve.
|
||||
//
|
||||
// If listener is not an instance of *GracefulListener it will be wrapped
|
||||
// to become one.
|
||||
func (gs *GracefulServer) Serve(listener net.Listener) error {
|
||||
// Accept a net.Listener to preserve the interface compatibility with the
|
||||
// standard http.Server. If it is not a GracefulListener then wrap it into
|
||||
// one.
|
||||
gracefulListener, ok := listener.(*GracefulListener)
|
||||
if !ok {
|
||||
gracefulListener = NewListener(listener)
|
||||
listener = gracefulListener
|
||||
}
|
||||
listenerUnsafePtr := unsafe.Pointer(gs.listener)
|
||||
atomic.StorePointer(&listenerUnsafePtr, unsafe.Pointer(gracefulListener))
|
||||
|
||||
// Wrap the server HTTP handler into graceful one, that will close kept
|
||||
// alive connections if a new request is received after shutdown.
|
||||
gracefulHandler := newGracefulHandler(gs.Server.Handler)
|
||||
gs.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() {
|
||||
gs.shutdown <- true
|
||||
close(gs.shutdown)
|
||||
gracefulHandler.Close()
|
||||
gs.Server.SetKeepAlivesEnabled(false)
|
||||
gracefulListener.Close()
|
||||
}()
|
||||
|
||||
originalConnState := gs.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.
|
||||
gs.ConnState = func(conn net.Conn, newState http.ConnState) {
|
||||
gs.connToPropsMtx.RLock()
|
||||
connProps := gs.connToProps[conn]
|
||||
gs.connToPropsMtx.RUnlock()
|
||||
|
||||
switch newState {
|
||||
|
||||
case http.StateNew:
|
||||
// New connection -> StateNew
|
||||
connProps.protected = true
|
||||
gs.StartRoutine()
|
||||
|
||||
case http.StateActive:
|
||||
// (StateNew, StateIdle) -> StateActive
|
||||
if gracefulHandler.IsClosed() {
|
||||
conn.Close()
|
||||
break
|
||||
}
|
||||
|
||||
if !connProps.protected {
|
||||
connProps.protected = true
|
||||
gs.StartRoutine()
|
||||
}
|
||||
|
||||
default:
|
||||
// (StateNew, StateActive) -> (StateIdle, StateClosed, StateHiJacked)
|
||||
if connProps.protected {
|
||||
gs.FinishRoutine()
|
||||
connProps.protected = false
|
||||
}
|
||||
}
|
||||
|
||||
if gs.stateHandler != nil {
|
||||
gs.stateHandler(conn, connProps.state, newState)
|
||||
}
|
||||
connProps.state = newState
|
||||
|
||||
gs.connToPropsMtx.Lock()
|
||||
if newState == http.StateClosed || newState == http.StateHijacked {
|
||||
delete(gs.connToProps, conn)
|
||||
} else {
|
||||
gs.connToProps[conn] = connProps
|
||||
}
|
||||
gs.connToPropsMtx.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 gs.up != nil {
|
||||
gs.up <- listener
|
||||
}
|
||||
|
||||
err := gs.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.
|
||||
gs.wg.Wait()
|
||||
gs.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 (gs *GracefulServer) StartRoutine() {
|
||||
gs.wg.Add(1)
|
||||
atomic.AddInt32(&gs.routinesCount, 1)
|
||||
}
|
||||
|
||||
// FinishRoutine decrements the server's WaitGroup. Use this to complement
|
||||
// StartRoutine().
|
||||
func (gs *GracefulServer) FinishRoutine() {
|
||||
gs.wg.Done()
|
||||
atomic.AddInt32(&gs.routinesCount, -1)
|
||||
}
|
||||
|
||||
// RoutinesCount returns the number of currently running routines
|
||||
func (gs *GracefulServer) RoutinesCount() int {
|
||||
return int(atomic.LoadInt32(&gs.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
|
||||
}
|
||||
|
||||
// connProperties is used to keep track of various properties of connections
|
||||
// maintained by a gracefulServer.
|
||||
type connProperties struct {
|
||||
// Last known connection state.
|
||||
state http.ConnState
|
||||
// Tells whether the connection is going to defer server shutdown until
|
||||
// the current HTTP request is completed.
|
||||
protected bool
|
||||
}
|
47
vendor/github.com/mailgun/manners/static.go
generated
vendored
Normal file
47
vendor/github.com/mailgun/manners/static.go
generated
vendored
Normal file
|
@ -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()
|
||||
}
|
202
vendor/github.com/mailgun/timetools/LICENSE
generated
vendored
Normal file
202
vendor/github.com/mailgun/timetools/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,202 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
104
vendor/github.com/mailgun/timetools/provider.go
generated
vendored
Normal file
104
vendor/github.com/mailgun/timetools/provider.go
generated
vendored
Normal file
|
@ -0,0 +1,104 @@
|
|||
package timetools
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TimeProvider is an interface we use to mock time in tests.
|
||||
type TimeProvider interface {
|
||||
UtcNow() time.Time
|
||||
Sleep(time.Duration)
|
||||
After(time.Duration) <-chan time.Time
|
||||
}
|
||||
|
||||
// RealTime is a real clock time, used in production.
|
||||
type RealTime struct {
|
||||
}
|
||||
|
||||
func (*RealTime) UtcNow() time.Time {
|
||||
return time.Now().UTC()
|
||||
}
|
||||
|
||||
func (*RealTime) Sleep(d time.Duration) {
|
||||
time.Sleep(d)
|
||||
}
|
||||
|
||||
func (*RealTime) After(d time.Duration) <-chan time.Time {
|
||||
return time.After(d)
|
||||
}
|
||||
|
||||
// FreezedTime is manually controlled time for use in tests.
|
||||
type FreezedTime struct {
|
||||
CurrentTime time.Time
|
||||
}
|
||||
|
||||
func (t *FreezedTime) UtcNow() time.Time {
|
||||
return t.CurrentTime
|
||||
}
|
||||
|
||||
func (t *FreezedTime) Sleep(d time.Duration) {
|
||||
t.CurrentTime = t.CurrentTime.Add(d)
|
||||
}
|
||||
|
||||
func (t *FreezedTime) After(d time.Duration) <-chan time.Time {
|
||||
t.Sleep(d)
|
||||
c := make(chan time.Time, 1)
|
||||
c <- t.CurrentTime
|
||||
return c
|
||||
}
|
||||
|
||||
type sleepableTime struct {
|
||||
currentTime time.Time
|
||||
waiters map[time.Time][]chan time.Time
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// SleepProvider returns a TimeProvider that has good fakes for
|
||||
// time.Sleep and time.After. Both functions will behave as if
|
||||
// time is frozen until you call AdvanceTimeBy, at which point
|
||||
// any calls to time.Sleep that should return do return and
|
||||
// any ticks from time.After that should happen do happen.
|
||||
func SleepProvider(currentTime time.Time) TimeProvider {
|
||||
return &sleepableTime{
|
||||
currentTime: currentTime,
|
||||
waiters: make(map[time.Time][]chan time.Time),
|
||||
}
|
||||
}
|
||||
|
||||
func (t *sleepableTime) UtcNow() time.Time {
|
||||
return t.currentTime
|
||||
}
|
||||
|
||||
func (t *sleepableTime) Sleep(d time.Duration) {
|
||||
<-t.After(d)
|
||||
}
|
||||
|
||||
func (t *sleepableTime) After(d time.Duration) <-chan time.Time {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
||||
c := make(chan time.Time, 1)
|
||||
until := t.currentTime.Add(d)
|
||||
t.waiters[until] = append(t.waiters[until], c)
|
||||
return c
|
||||
}
|
||||
|
||||
// AdvanceTimeBy simulates advancing time by some time.Duration d.
|
||||
// This function panics if st is not the result of a call to
|
||||
// SleepProvider.
|
||||
func AdvanceTimeBy(st TimeProvider, d time.Duration) {
|
||||
t := st.(*sleepableTime)
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
||||
t.currentTime = t.currentTime.Add(d)
|
||||
for k, v := range t.waiters {
|
||||
if k.Before(t.currentTime) {
|
||||
for _, c := range v {
|
||||
c <- t.currentTime
|
||||
}
|
||||
delete(t.waiters, k)
|
||||
}
|
||||
}
|
||||
}
|
59
vendor/github.com/mailgun/timetools/rfc2822time.go
generated
vendored
Normal file
59
vendor/github.com/mailgun/timetools/rfc2822time.go
generated
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
package timetools
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
)
|
||||
|
||||
// We use RFC2822 format for timestamps everywhere ('Thu, 13 Oct 2011 18:02:00 GMT'), but
|
||||
// by default Go's JSON package uses another format when decoding/encoding timestamps.
|
||||
// That's why we declare our own timestamp type and implement its marshal/unmarshal methods
|
||||
// so JSON package decodes/encodes it properly.
|
||||
type RFC2822Time time.Time
|
||||
|
||||
func NewRFC2822Time(timestamp int64) RFC2822Time {
|
||||
return RFC2822Time(time.Unix(timestamp, 0).UTC())
|
||||
}
|
||||
|
||||
func (t RFC2822Time) Unix() int64 {
|
||||
return time.Time(t).Unix()
|
||||
}
|
||||
|
||||
func (t RFC2822Time) IsZero() bool {
|
||||
return time.Time(t).IsZero()
|
||||
}
|
||||
|
||||
func (t RFC2822Time) MarshalJSON() ([]byte, error) {
|
||||
return []byte(strconv.Quote(time.Time(t).Format(time.RFC1123))), nil
|
||||
}
|
||||
|
||||
func (t *RFC2822Time) UnmarshalJSON(s []byte) error {
|
||||
q, err := strconv.Unquote(string(s))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if *(*time.Time)(t), err = time.Parse(time.RFC1123, q); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t RFC2822Time) GetBSON() (interface{}, error) {
|
||||
return time.Time(t), nil
|
||||
}
|
||||
|
||||
func (t *RFC2822Time) SetBSON(raw bson.Raw) error {
|
||||
var result time.Time
|
||||
err := raw.Unmarshal(&result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*t = RFC2822Time(result)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t RFC2822Time) String() string {
|
||||
return time.Time(t).Format(time.RFC1123)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue