github.com/djarvur/go-swagger@v0.18.0/examples/todo-list/restapi/server.go (about)

     1  // Code generated by go-swagger; DO NOT EDIT.
     2  
     3  package restapi
     4  
     5  import (
     6  	"context"
     7  	"crypto/tls"
     8  	"crypto/x509"
     9  	"errors"
    10  	"fmt"
    11  	"io/ioutil"
    12  	"log"
    13  	"net"
    14  	"net/http"
    15  	"os"
    16  	"os/signal"
    17  	"strconv"
    18  	"sync"
    19  	"sync/atomic"
    20  	"syscall"
    21  	"time"
    22  
    23  	"github.com/go-openapi/runtime/flagext"
    24  	"github.com/go-openapi/swag"
    25  	flag "github.com/spf13/pflag"
    26  	"golang.org/x/net/netutil"
    27  
    28  	"github.com/go-swagger/go-swagger/examples/todo-list/restapi/operations"
    29  )
    30  
    31  const (
    32  	schemeHTTP  = "http"
    33  	schemeHTTPS = "https"
    34  	schemeUnix  = "unix"
    35  )
    36  
    37  var defaultSchemes []string
    38  
    39  func init() {
    40  	defaultSchemes = []string{
    41  		schemeHTTP,
    42  		schemeHTTPS,
    43  		schemeUnix,
    44  	}
    45  }
    46  
    47  var (
    48  	enabledListeners []string
    49  	cleanupTimeout   time.Duration
    50  	gracefulTimeout  time.Duration
    51  	maxHeaderSize    flagext.ByteSize
    52  
    53  	socketPath string
    54  
    55  	host         string
    56  	port         int
    57  	listenLimit  int
    58  	keepAlive    time.Duration
    59  	readTimeout  time.Duration
    60  	writeTimeout time.Duration
    61  
    62  	tlsHost           string
    63  	tlsPort           int
    64  	tlsListenLimit    int
    65  	tlsKeepAlive      time.Duration
    66  	tlsReadTimeout    time.Duration
    67  	tlsWriteTimeout   time.Duration
    68  	tlsCertificate    string
    69  	tlsCertificateKey string
    70  	tlsCACertificate  string
    71  )
    72  
    73  func init() {
    74  	maxHeaderSize = flagext.ByteSize(1000000)
    75  
    76  	flag.StringSliceVar(&enabledListeners, "scheme", defaultSchemes, "the listeners to enable, this can be repeated and defaults to the schemes in the swagger spec")
    77  	flag.DurationVar(&cleanupTimeout, "cleanup-timeout", 10*time.Second, "grace period for which to wait before killing idle connections")
    78  	flag.DurationVar(&gracefulTimeout, "graceful-timeout", 15*time.Second, "grace period for which to wait before shutting down the server")
    79  	flag.Var(&maxHeaderSize, "max-header-size", "controls the maximum number of bytes the server will read parsing the request header's keys and values, including the request line. It does not limit the size of the request body")
    80  
    81  	flag.StringVar(&socketPath, "socket-path", "/var/run/todo-list.sock", "the unix socket to listen on")
    82  
    83  	flag.StringVar(&host, "host", "localhost", "the IP to listen on")
    84  	flag.IntVar(&port, "port", 0, "the port to listen on for insecure connections, defaults to a random value")
    85  	flag.IntVar(&listenLimit, "listen-limit", 0, "limit the number of outstanding requests")
    86  	flag.DurationVar(&keepAlive, "keep-alive", 3*time.Minute, "sets the TCP keep-alive timeouts on accepted connections. It prunes dead TCP connections ( e.g. closing laptop mid-download)")
    87  	flag.DurationVar(&readTimeout, "read-timeout", 30*time.Second, "maximum duration before timing out read of the request")
    88  	flag.DurationVar(&writeTimeout, "write-timeout", 30*time.Second, "maximum duration before timing out write of the response")
    89  
    90  	flag.StringVar(&tlsHost, "tls-host", "localhost", "the IP to listen on")
    91  	flag.IntVar(&tlsPort, "tls-port", 0, "the port to listen on for secure connections, defaults to a random value")
    92  	flag.StringVar(&tlsCertificate, "tls-certificate", "", "the certificate file to use for secure connections")
    93  	flag.StringVar(&tlsCertificateKey, "tls-key", "", "the private key file to use for secure connections (without passphrase)")
    94  	flag.StringVar(&tlsCACertificate, "tls-ca", "", "the certificate authority certificate file to be used with mutual tls auth")
    95  	flag.IntVar(&tlsListenLimit, "tls-listen-limit", 0, "limit the number of outstanding requests")
    96  	flag.DurationVar(&tlsKeepAlive, "tls-keep-alive", 3*time.Minute, "sets the TCP keep-alive timeouts on accepted connections. It prunes dead TCP connections ( e.g. closing laptop mid-download)")
    97  	flag.DurationVar(&tlsReadTimeout, "tls-read-timeout", 30*time.Second, "maximum duration before timing out read of the request")
    98  	flag.DurationVar(&tlsWriteTimeout, "tls-write-timeout", 30*time.Second, "maximum duration before timing out write of the response")
    99  }
   100  
   101  func stringEnvOverride(orig string, def string, keys ...string) string {
   102  	for _, k := range keys {
   103  		if os.Getenv(k) != "" {
   104  			return os.Getenv(k)
   105  		}
   106  	}
   107  	if def != "" && orig == "" {
   108  		return def
   109  	}
   110  	return orig
   111  }
   112  
   113  func intEnvOverride(orig int, def int, keys ...string) int {
   114  	for _, k := range keys {
   115  		if os.Getenv(k) != "" {
   116  			v, err := strconv.Atoi(os.Getenv(k))
   117  			if err != nil {
   118  				fmt.Fprintln(os.Stderr, k, "is not a valid number")
   119  				os.Exit(1)
   120  			}
   121  			return v
   122  		}
   123  	}
   124  	if def != 0 && orig == 0 {
   125  		return def
   126  	}
   127  	return orig
   128  }
   129  
   130  // NewServer creates a new api todo list server but does not configure it
   131  func NewServer(api *operations.TodoListAPI) *Server {
   132  	s := new(Server)
   133  
   134  	s.EnabledListeners = enabledListeners
   135  	s.CleanupTimeout = cleanupTimeout
   136  	s.GracefulTimeout = gracefulTimeout
   137  	s.MaxHeaderSize = maxHeaderSize
   138  	s.SocketPath = socketPath
   139  	s.Host = stringEnvOverride(host, "", "HOST")
   140  	s.Port = intEnvOverride(port, 0, "PORT")
   141  	s.ListenLimit = listenLimit
   142  	s.KeepAlive = keepAlive
   143  	s.ReadTimeout = readTimeout
   144  	s.WriteTimeout = writeTimeout
   145  	s.TLSHost = stringEnvOverride(tlsHost, s.Host, "TLS_HOST", "HOST")
   146  	s.TLSPort = intEnvOverride(tlsPort, 0, "TLS_PORT")
   147  	s.TLSCertificate = stringEnvOverride(tlsCertificate, "", "TLS_CERTIFICATE")
   148  	s.TLSCertificateKey = stringEnvOverride(tlsCertificateKey, "", "TLS_PRIVATE_KEY")
   149  	s.TLSCACertificate = stringEnvOverride(tlsCACertificate, "", "TLS_CA_CERTIFICATE")
   150  	s.TLSListenLimit = tlsListenLimit
   151  	s.TLSKeepAlive = tlsKeepAlive
   152  	s.TLSReadTimeout = tlsReadTimeout
   153  	s.TLSWriteTimeout = tlsWriteTimeout
   154  	s.shutdown = make(chan struct{})
   155  	s.api = api
   156  	s.interrupt = make(chan os.Signal, 1)
   157  	return s
   158  }
   159  
   160  // ConfigureAPI configures the API and handlers.
   161  func (s *Server) ConfigureAPI() {
   162  	if s.api != nil {
   163  		s.handler = configureAPI(s.api)
   164  	}
   165  }
   166  
   167  // ConfigureFlags configures the additional flags defined by the handlers. Needs to be called before the parser.Parse
   168  func (s *Server) ConfigureFlags() {
   169  	if s.api != nil {
   170  		configureFlags(s.api)
   171  	}
   172  }
   173  
   174  // Server for the todo list API
   175  type Server struct {
   176  	EnabledListeners []string
   177  	CleanupTimeout   time.Duration
   178  	GracefulTimeout  time.Duration
   179  	MaxHeaderSize    flagext.ByteSize
   180  
   181  	SocketPath    string
   182  	domainSocketL net.Listener
   183  
   184  	Host         string
   185  	Port         int
   186  	ListenLimit  int
   187  	KeepAlive    time.Duration
   188  	ReadTimeout  time.Duration
   189  	WriteTimeout time.Duration
   190  	httpServerL  net.Listener
   191  
   192  	TLSHost           string
   193  	TLSPort           int
   194  	TLSCertificate    string
   195  	TLSCertificateKey string
   196  	TLSCACertificate  string
   197  	TLSListenLimit    int
   198  	TLSKeepAlive      time.Duration
   199  	TLSReadTimeout    time.Duration
   200  	TLSWriteTimeout   time.Duration
   201  	httpsServerL      net.Listener
   202  
   203  	api          *operations.TodoListAPI
   204  	handler      http.Handler
   205  	hasListeners bool
   206  	shutdown     chan struct{}
   207  	shuttingDown int32
   208  	interrupted  bool
   209  	interrupt    chan os.Signal
   210  }
   211  
   212  // Logf logs message either via defined user logger or via system one if no user logger is defined.
   213  func (s *Server) Logf(f string, args ...interface{}) {
   214  	if s.api != nil && s.api.Logger != nil {
   215  		s.api.Logger(f, args...)
   216  	} else {
   217  		log.Printf(f, args...)
   218  	}
   219  }
   220  
   221  // Fatalf logs message either via defined user logger or via system one if no user logger is defined.
   222  // Exits with non-zero status after printing
   223  func (s *Server) Fatalf(f string, args ...interface{}) {
   224  	if s.api != nil && s.api.Logger != nil {
   225  		s.api.Logger(f, args...)
   226  		os.Exit(1)
   227  	} else {
   228  		log.Fatalf(f, args...)
   229  	}
   230  }
   231  
   232  // SetAPI configures the server with the specified API. Needs to be called before Serve
   233  func (s *Server) SetAPI(api *operations.TodoListAPI) {
   234  	if api == nil {
   235  		s.api = nil
   236  		s.handler = nil
   237  		return
   238  	}
   239  
   240  	s.api = api
   241  	s.api.Logger = log.Printf
   242  	s.handler = configureAPI(api)
   243  }
   244  
   245  func (s *Server) hasScheme(scheme string) bool {
   246  	schemes := s.EnabledListeners
   247  	if len(schemes) == 0 {
   248  		schemes = defaultSchemes
   249  	}
   250  
   251  	for _, v := range schemes {
   252  		if v == scheme {
   253  			return true
   254  		}
   255  	}
   256  	return false
   257  }
   258  
   259  // Serve the api
   260  func (s *Server) Serve() (err error) {
   261  	if !s.hasListeners {
   262  		if err = s.Listen(); err != nil {
   263  			return err
   264  		}
   265  	}
   266  
   267  	// set default handler, if none is set
   268  	if s.handler == nil {
   269  		if s.api == nil {
   270  			return errors.New("can't create the default handler, as no api is set")
   271  		}
   272  
   273  		s.SetHandler(s.api.Serve(nil))
   274  	}
   275  
   276  	wg := new(sync.WaitGroup)
   277  	once := new(sync.Once)
   278  	signalNotify(s.interrupt)
   279  	go handleInterrupt(once, s)
   280  
   281  	servers := []*http.Server{}
   282  	wg.Add(1)
   283  	go s.handleShutdown(wg, &servers)
   284  
   285  	if s.hasScheme(schemeUnix) {
   286  		domainSocket := new(http.Server)
   287  		domainSocket.MaxHeaderBytes = int(s.MaxHeaderSize)
   288  		domainSocket.Handler = s.handler
   289  		if int64(s.CleanupTimeout) > 0 {
   290  			domainSocket.IdleTimeout = s.CleanupTimeout
   291  		}
   292  
   293  		configureServer(domainSocket, "unix", string(s.SocketPath))
   294  
   295  		servers = append(servers, domainSocket)
   296  		wg.Add(1)
   297  		s.Logf("Serving todo list at unix://%s", s.SocketPath)
   298  		go func(l net.Listener) {
   299  			defer wg.Done()
   300  			if err := domainSocket.Serve(l); err != nil && err != http.ErrServerClosed {
   301  				s.Fatalf("%v", err)
   302  			}
   303  			s.Logf("Stopped serving todo list at unix://%s", s.SocketPath)
   304  		}(s.domainSocketL)
   305  	}
   306  
   307  	if s.hasScheme(schemeHTTP) {
   308  		httpServer := new(http.Server)
   309  		httpServer.MaxHeaderBytes = int(s.MaxHeaderSize)
   310  		httpServer.ReadTimeout = s.ReadTimeout
   311  		httpServer.WriteTimeout = s.WriteTimeout
   312  		httpServer.SetKeepAlivesEnabled(int64(s.KeepAlive) > 0)
   313  		if s.ListenLimit > 0 {
   314  			s.httpServerL = netutil.LimitListener(s.httpServerL, s.ListenLimit)
   315  		}
   316  
   317  		if int64(s.CleanupTimeout) > 0 {
   318  			httpServer.IdleTimeout = s.CleanupTimeout
   319  		}
   320  
   321  		httpServer.Handler = s.handler
   322  
   323  		configureServer(httpServer, "http", s.httpServerL.Addr().String())
   324  
   325  		servers = append(servers, httpServer)
   326  		wg.Add(1)
   327  		s.Logf("Serving todo list at http://%s", s.httpServerL.Addr())
   328  		go func(l net.Listener) {
   329  			defer wg.Done()
   330  			if err := httpServer.Serve(l); err != nil && err != http.ErrServerClosed {
   331  				s.Fatalf("%v", err)
   332  			}
   333  			s.Logf("Stopped serving todo list at http://%s", l.Addr())
   334  		}(s.httpServerL)
   335  	}
   336  
   337  	if s.hasScheme(schemeHTTPS) {
   338  		httpsServer := new(http.Server)
   339  		httpsServer.MaxHeaderBytes = int(s.MaxHeaderSize)
   340  		httpsServer.ReadTimeout = s.TLSReadTimeout
   341  		httpsServer.WriteTimeout = s.TLSWriteTimeout
   342  		httpsServer.SetKeepAlivesEnabled(int64(s.TLSKeepAlive) > 0)
   343  		if s.TLSListenLimit > 0 {
   344  			s.httpsServerL = netutil.LimitListener(s.httpsServerL, s.TLSListenLimit)
   345  		}
   346  		if int64(s.CleanupTimeout) > 0 {
   347  			httpsServer.IdleTimeout = s.CleanupTimeout
   348  		}
   349  		httpsServer.Handler = s.handler
   350  
   351  		// Inspired by https://blog.bracebin.com/achieving-perfect-ssl-labs-score-with-go
   352  		httpsServer.TLSConfig = &tls.Config{
   353  			// Causes servers to use Go's default ciphersuite preferences,
   354  			// which are tuned to avoid attacks. Does nothing on clients.
   355  			PreferServerCipherSuites: true,
   356  			// Only use curves which have assembly implementations
   357  			// https://github.com/golang/go/tree/master/src/crypto/elliptic
   358  			CurvePreferences: []tls.CurveID{tls.CurveP256},
   359  			// Use modern tls mode https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility
   360  			NextProtos: []string{"http/1.1", "h2"},
   361  			// https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_Sheet#Rule_-_Only_Support_Strong_Protocols
   362  			MinVersion: tls.VersionTLS12,
   363  			// These ciphersuites support Forward Secrecy: https://en.wikipedia.org/wiki/Forward_secrecy
   364  			CipherSuites: []uint16{
   365  				tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
   366  				tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
   367  				tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
   368  				tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
   369  				tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
   370  				tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
   371  			},
   372  		}
   373  
   374  		// build standard config from server options
   375  		if s.TLSCertificate != "" && s.TLSCertificateKey != "" {
   376  			httpsServer.TLSConfig.Certificates = make([]tls.Certificate, 1)
   377  			httpsServer.TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(s.TLSCertificate, s.TLSCertificateKey)
   378  			if err != nil {
   379  				return err
   380  			}
   381  		}
   382  
   383  		if s.TLSCACertificate != "" {
   384  			// include specified CA certificate
   385  			caCert, caCertErr := ioutil.ReadFile(s.TLSCACertificate)
   386  			if caCertErr != nil {
   387  				return caCertErr
   388  			}
   389  			caCertPool := x509.NewCertPool()
   390  			ok := caCertPool.AppendCertsFromPEM(caCert)
   391  			if !ok {
   392  				return fmt.Errorf("cannot parse CA certificate")
   393  			}
   394  			httpsServer.TLSConfig.ClientCAs = caCertPool
   395  			httpsServer.TLSConfig.ClientAuth = tls.RequireAndVerifyClientCert
   396  		}
   397  
   398  		// call custom TLS configurator
   399  		configureTLS(httpsServer.TLSConfig)
   400  
   401  		if len(httpsServer.TLSConfig.Certificates) == 0 {
   402  			// after standard and custom config are passed, this ends up with no certificate
   403  			if s.TLSCertificate == "" {
   404  				if s.TLSCertificateKey == "" {
   405  					s.Fatalf("the required flags `--tls-certificate` and `--tls-key` were not specified")
   406  				}
   407  				s.Fatalf("the required flag `--tls-certificate` was not specified")
   408  			}
   409  			if s.TLSCertificateKey == "" {
   410  				s.Fatalf("the required flag `--tls-key` was not specified")
   411  			}
   412  			// this happens with a wrong custom TLS configurator
   413  			s.Fatalf("no certificate was configured for TLS")
   414  		}
   415  
   416  		// must have at least one certificate or panics
   417  		httpsServer.TLSConfig.BuildNameToCertificate()
   418  
   419  		configureServer(httpsServer, "https", s.httpsServerL.Addr().String())
   420  
   421  		servers = append(servers, httpsServer)
   422  		wg.Add(1)
   423  		s.Logf("Serving todo list at https://%s", s.httpsServerL.Addr())
   424  		go func(l net.Listener) {
   425  			defer wg.Done()
   426  			if err := httpsServer.Serve(l); err != nil && err != http.ErrServerClosed {
   427  				s.Fatalf("%v", err)
   428  			}
   429  			s.Logf("Stopped serving todo list at https://%s", l.Addr())
   430  		}(tls.NewListener(s.httpsServerL, httpsServer.TLSConfig))
   431  	}
   432  
   433  	wg.Wait()
   434  	return nil
   435  }
   436  
   437  // Listen creates the listeners for the server
   438  func (s *Server) Listen() error {
   439  	if s.hasListeners { // already done this
   440  		return nil
   441  	}
   442  
   443  	if s.hasScheme(schemeHTTPS) {
   444  		// Use http host if https host wasn't defined
   445  		if s.TLSHost == "" {
   446  			s.TLSHost = s.Host
   447  		}
   448  		// Use http listen limit if https listen limit wasn't defined
   449  		if s.TLSListenLimit == 0 {
   450  			s.TLSListenLimit = s.ListenLimit
   451  		}
   452  		// Use http tcp keep alive if https tcp keep alive wasn't defined
   453  		if int64(s.TLSKeepAlive) == 0 {
   454  			s.TLSKeepAlive = s.KeepAlive
   455  		}
   456  		// Use http read timeout if https read timeout wasn't defined
   457  		if int64(s.TLSReadTimeout) == 0 {
   458  			s.TLSReadTimeout = s.ReadTimeout
   459  		}
   460  		// Use http write timeout if https write timeout wasn't defined
   461  		if int64(s.TLSWriteTimeout) == 0 {
   462  			s.TLSWriteTimeout = s.WriteTimeout
   463  		}
   464  	}
   465  
   466  	if s.hasScheme(schemeUnix) {
   467  		domSockListener, err := net.Listen("unix", string(s.SocketPath))
   468  		if err != nil {
   469  			return err
   470  		}
   471  		s.domainSocketL = domSockListener
   472  	}
   473  
   474  	if s.hasScheme(schemeHTTP) {
   475  		listener, err := net.Listen("tcp", net.JoinHostPort(s.Host, strconv.Itoa(s.Port)))
   476  		if err != nil {
   477  			return err
   478  		}
   479  
   480  		h, p, err := swag.SplitHostPort(listener.Addr().String())
   481  		if err != nil {
   482  			return err
   483  		}
   484  		s.Host = h
   485  		s.Port = p
   486  		s.httpServerL = listener
   487  	}
   488  
   489  	if s.hasScheme(schemeHTTPS) {
   490  		tlsListener, err := net.Listen("tcp", net.JoinHostPort(s.TLSHost, strconv.Itoa(s.TLSPort)))
   491  		if err != nil {
   492  			return err
   493  		}
   494  
   495  		sh, sp, err := swag.SplitHostPort(tlsListener.Addr().String())
   496  		if err != nil {
   497  			return err
   498  		}
   499  		s.TLSHost = sh
   500  		s.TLSPort = sp
   501  		s.httpsServerL = tlsListener
   502  	}
   503  
   504  	s.hasListeners = true
   505  	return nil
   506  }
   507  
   508  // Shutdown server and clean up resources
   509  func (s *Server) Shutdown() error {
   510  	if atomic.CompareAndSwapInt32(&s.shuttingDown, 0, 1) {
   511  		close(s.shutdown)
   512  	}
   513  	return nil
   514  }
   515  
   516  func (s *Server) handleShutdown(wg *sync.WaitGroup, serversPtr *[]*http.Server) {
   517  	// wg.Done must occur last, after s.api.ServerShutdown()
   518  	// (to preserve old behaviour)
   519  	defer wg.Done()
   520  
   521  	<-s.shutdown
   522  
   523  	servers := *serversPtr
   524  
   525  	ctx, cancel := context.WithTimeout(context.TODO(), s.GracefulTimeout)
   526  	defer cancel()
   527  
   528  	shutdownChan := make(chan bool)
   529  	for i := range servers {
   530  		server := servers[i]
   531  		go func() {
   532  			var success bool
   533  			defer func() {
   534  				shutdownChan <- success
   535  			}()
   536  			if err := server.Shutdown(ctx); err != nil {
   537  				// Error from closing listeners, or context timeout:
   538  				s.Logf("HTTP server Shutdown: %v", err)
   539  			} else {
   540  				success = true
   541  			}
   542  		}()
   543  	}
   544  
   545  	// Wait until all listeners have successfully shut down before calling ServerShutdown
   546  	success := true
   547  	for range servers {
   548  		success = success && <-shutdownChan
   549  	}
   550  	if success {
   551  		s.api.ServerShutdown()
   552  	}
   553  }
   554  
   555  // GetHandler returns a handler useful for testing
   556  func (s *Server) GetHandler() http.Handler {
   557  	return s.handler
   558  }
   559  
   560  // SetHandler allows for setting a http handler on this server
   561  func (s *Server) SetHandler(handler http.Handler) {
   562  	s.handler = handler
   563  }
   564  
   565  // UnixListener returns the domain socket listener
   566  func (s *Server) UnixListener() (net.Listener, error) {
   567  	if !s.hasListeners {
   568  		if err := s.Listen(); err != nil {
   569  			return nil, err
   570  		}
   571  	}
   572  	return s.domainSocketL, nil
   573  }
   574  
   575  // HTTPListener returns the http listener
   576  func (s *Server) HTTPListener() (net.Listener, error) {
   577  	if !s.hasListeners {
   578  		if err := s.Listen(); err != nil {
   579  			return nil, err
   580  		}
   581  	}
   582  	return s.httpServerL, nil
   583  }
   584  
   585  // TLSListener returns the https listener
   586  func (s *Server) TLSListener() (net.Listener, error) {
   587  	if !s.hasListeners {
   588  		if err := s.Listen(); err != nil {
   589  			return nil, err
   590  		}
   591  	}
   592  	return s.httpsServerL, nil
   593  }
   594  
   595  func handleInterrupt(once *sync.Once, s *Server) {
   596  	once.Do(func() {
   597  		for _ = range s.interrupt {
   598  			if s.interrupted {
   599  				s.Logf("Server already shutting down")
   600  				continue
   601  			}
   602  			s.interrupted = true
   603  			s.Logf("Shutting down... ")
   604  			if err := s.Shutdown(); err != nil {
   605  				s.Logf("HTTP server Shutdown: %v", err)
   606  			}
   607  		}
   608  	})
   609  }
   610  
   611  func signalNotify(interrupt chan<- os.Signal) {
   612  	signal.Notify(interrupt, syscall.SIGINT, syscall.SIGTERM)
   613  }