github.com/josephspurrier/go-swagger@v0.2.1-0.20221129144919-1f672a142a00/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  	"log"
    12  	"net"
    13  	"net/http"
    14  	"os"
    15  	"os/signal"
    16  	"strconv"
    17  	"sync"
    18  	"sync/atomic"
    19  	"syscall"
    20  	"time"
    21  
    22  	"github.com/go-openapi/runtime/flagext"
    23  	"github.com/go-openapi/swag"
    24  	flag "github.com/spf13/pflag"
    25  	"golang.org/x/net/netutil"
    26  
    27  	"github.com/go-swagger/go-swagger/examples/todo-list/restapi/operations"
    28  )
    29  
    30  const (
    31  	schemeHTTP  = "http"
    32  	schemeHTTPS = "https"
    33  	schemeUnix  = "unix"
    34  )
    35  
    36  var defaultSchemes []string
    37  
    38  func init() {
    39  	defaultSchemes = []string{
    40  		schemeHTTP,
    41  		schemeHTTPS,
    42  		schemeUnix,
    43  	}
    44  }
    45  
    46  var (
    47  	enabledListeners []string
    48  	cleanupTimeout   time.Duration
    49  	gracefulTimeout  time.Duration
    50  	maxHeaderSize    flagext.ByteSize
    51  
    52  	socketPath string
    53  
    54  	host         string
    55  	port         int
    56  	listenLimit  int
    57  	keepAlive    time.Duration
    58  	readTimeout  time.Duration
    59  	writeTimeout time.Duration
    60  
    61  	tlsHost           string
    62  	tlsPort           int
    63  	tlsListenLimit    int
    64  	tlsKeepAlive      time.Duration
    65  	tlsReadTimeout    time.Duration
    66  	tlsWriteTimeout   time.Duration
    67  	tlsCertificate    string
    68  	tlsCertificateKey string
    69  	tlsCACertificate  string
    70  )
    71  
    72  func init() {
    73  	maxHeaderSize = flagext.ByteSize(1000000)
    74  
    75  	flag.StringSliceVar(&enabledListeners, "scheme", defaultSchemes, "the listeners to enable, this can be repeated and defaults to the schemes in the swagger spec")
    76  
    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.handler = configureAPI(api)
   242  }
   243  
   244  func (s *Server) hasScheme(scheme string) bool {
   245  	schemes := s.EnabledListeners
   246  	if len(schemes) == 0 {
   247  		schemes = defaultSchemes
   248  	}
   249  
   250  	for _, v := range schemes {
   251  		if v == scheme {
   252  			return true
   253  		}
   254  	}
   255  	return false
   256  }
   257  
   258  // Serve the api
   259  func (s *Server) Serve() (err error) {
   260  	if !s.hasListeners {
   261  		if err = s.Listen(); err != nil {
   262  			return err
   263  		}
   264  	}
   265  
   266  	// set default handler, if none is set
   267  	if s.handler == nil {
   268  		if s.api == nil {
   269  			return errors.New("can't create the default handler, as no api is set")
   270  		}
   271  
   272  		s.SetHandler(s.api.Serve(nil))
   273  	}
   274  
   275  	wg := new(sync.WaitGroup)
   276  	once := new(sync.Once)
   277  	signalNotify(s.interrupt)
   278  	go handleInterrupt(once, s)
   279  
   280  	servers := []*http.Server{}
   281  
   282  	if s.hasScheme(schemeUnix) {
   283  		domainSocket := new(http.Server)
   284  		domainSocket.MaxHeaderBytes = int(s.MaxHeaderSize)
   285  		domainSocket.Handler = s.handler
   286  		if int64(s.CleanupTimeout) > 0 {
   287  			domainSocket.IdleTimeout = s.CleanupTimeout
   288  		}
   289  
   290  		configureServer(domainSocket, "unix", string(s.SocketPath))
   291  
   292  		servers = append(servers, domainSocket)
   293  		wg.Add(1)
   294  		s.Logf("Serving todo list at unix://%s", s.SocketPath)
   295  		go func(l net.Listener) {
   296  			defer wg.Done()
   297  			if err := domainSocket.Serve(l); err != nil && err != http.ErrServerClosed {
   298  				s.Fatalf("%v", err)
   299  			}
   300  			s.Logf("Stopped serving todo list at unix://%s", s.SocketPath)
   301  		}(s.domainSocketL)
   302  	}
   303  
   304  	if s.hasScheme(schemeHTTP) {
   305  		httpServer := new(http.Server)
   306  		httpServer.MaxHeaderBytes = int(s.MaxHeaderSize)
   307  		httpServer.ReadTimeout = s.ReadTimeout
   308  		httpServer.WriteTimeout = s.WriteTimeout
   309  		httpServer.SetKeepAlivesEnabled(int64(s.KeepAlive) > 0)
   310  		if s.ListenLimit > 0 {
   311  			s.httpServerL = netutil.LimitListener(s.httpServerL, s.ListenLimit)
   312  		}
   313  
   314  		if int64(s.CleanupTimeout) > 0 {
   315  			httpServer.IdleTimeout = s.CleanupTimeout
   316  		}
   317  
   318  		httpServer.Handler = s.handler
   319  
   320  		configureServer(httpServer, "http", s.httpServerL.Addr().String())
   321  
   322  		servers = append(servers, httpServer)
   323  		wg.Add(1)
   324  		s.Logf("Serving todo list at http://%s", s.httpServerL.Addr())
   325  		go func(l net.Listener) {
   326  			defer wg.Done()
   327  			if err := httpServer.Serve(l); err != nil && err != http.ErrServerClosed {
   328  				s.Fatalf("%v", err)
   329  			}
   330  			s.Logf("Stopped serving todo list at http://%s", l.Addr())
   331  		}(s.httpServerL)
   332  	}
   333  
   334  	if s.hasScheme(schemeHTTPS) {
   335  		httpsServer := new(http.Server)
   336  		httpsServer.MaxHeaderBytes = int(s.MaxHeaderSize)
   337  		httpsServer.ReadTimeout = s.TLSReadTimeout
   338  		httpsServer.WriteTimeout = s.TLSWriteTimeout
   339  		httpsServer.SetKeepAlivesEnabled(int64(s.TLSKeepAlive) > 0)
   340  		if s.TLSListenLimit > 0 {
   341  			s.httpsServerL = netutil.LimitListener(s.httpsServerL, s.TLSListenLimit)
   342  		}
   343  		if int64(s.CleanupTimeout) > 0 {
   344  			httpsServer.IdleTimeout = s.CleanupTimeout
   345  		}
   346  		httpsServer.Handler = s.handler
   347  
   348  		// Inspired by https://blog.bracebin.com/achieving-perfect-ssl-labs-score-with-go
   349  		httpsServer.TLSConfig = &tls.Config{
   350  			// Causes servers to use Go's default ciphersuite preferences,
   351  			// which are tuned to avoid attacks. Does nothing on clients.
   352  			PreferServerCipherSuites: true,
   353  			// Only use curves which have assembly implementations
   354  			// https://github.com/golang/go/tree/master/src/crypto/elliptic
   355  			CurvePreferences: []tls.CurveID{tls.CurveP256},
   356  			// Use modern tls mode https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility
   357  			NextProtos: []string{"h2", "http/1.1"},
   358  			// https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_Sheet#Rule_-_Only_Support_Strong_Protocols
   359  			MinVersion: tls.VersionTLS12,
   360  			// These ciphersuites support Forward Secrecy: https://en.wikipedia.org/wiki/Forward_secrecy
   361  			CipherSuites: []uint16{
   362  				tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
   363  				tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
   364  				tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
   365  				tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
   366  				tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
   367  				tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
   368  			},
   369  		}
   370  
   371  		// build standard config from server options
   372  		if s.TLSCertificate != "" && s.TLSCertificateKey != "" {
   373  			httpsServer.TLSConfig.Certificates = make([]tls.Certificate, 1)
   374  			httpsServer.TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(s.TLSCertificate, s.TLSCertificateKey)
   375  			if err != nil {
   376  				return err
   377  			}
   378  		}
   379  
   380  		if s.TLSCACertificate != "" {
   381  			// include specified CA certificate
   382  			caCert, caCertErr := os.ReadFile(s.TLSCACertificate)
   383  			if caCertErr != nil {
   384  				return caCertErr
   385  			}
   386  			caCertPool := x509.NewCertPool()
   387  			ok := caCertPool.AppendCertsFromPEM(caCert)
   388  			if !ok {
   389  				return fmt.Errorf("cannot parse CA certificate")
   390  			}
   391  			httpsServer.TLSConfig.ClientCAs = caCertPool
   392  			httpsServer.TLSConfig.ClientAuth = tls.RequireAndVerifyClientCert
   393  		}
   394  
   395  		// call custom TLS configurator
   396  		configureTLS(httpsServer.TLSConfig)
   397  
   398  		if len(httpsServer.TLSConfig.Certificates) == 0 && httpsServer.TLSConfig.GetCertificate == nil {
   399  			// after standard and custom config are passed, this ends up with no certificate
   400  			if s.TLSCertificate == "" {
   401  				if s.TLSCertificateKey == "" {
   402  					s.Fatalf("the required flags `--tls-certificate` and `--tls-key` were not specified")
   403  				}
   404  				s.Fatalf("the required flag `--tls-certificate` was not specified")
   405  			}
   406  			if s.TLSCertificateKey == "" {
   407  				s.Fatalf("the required flag `--tls-key` was not specified")
   408  			}
   409  			// this happens with a wrong custom TLS configurator
   410  			s.Fatalf("no certificate was configured for TLS")
   411  		}
   412  
   413  		configureServer(httpsServer, "https", s.httpsServerL.Addr().String())
   414  
   415  		servers = append(servers, httpsServer)
   416  		wg.Add(1)
   417  		s.Logf("Serving todo list at https://%s", s.httpsServerL.Addr())
   418  		go func(l net.Listener) {
   419  			defer wg.Done()
   420  			if err := httpsServer.Serve(l); err != nil && err != http.ErrServerClosed {
   421  				s.Fatalf("%v", err)
   422  			}
   423  			s.Logf("Stopped serving todo list at https://%s", l.Addr())
   424  		}(tls.NewListener(s.httpsServerL, httpsServer.TLSConfig))
   425  	}
   426  
   427  	wg.Add(1)
   428  	go s.handleShutdown(wg, &servers)
   429  
   430  	wg.Wait()
   431  	return nil
   432  }
   433  
   434  // Listen creates the listeners for the server
   435  func (s *Server) Listen() error {
   436  	if s.hasListeners { // already done this
   437  		return nil
   438  	}
   439  
   440  	if s.hasScheme(schemeHTTPS) {
   441  		// Use http host if https host wasn't defined
   442  		if s.TLSHost == "" {
   443  			s.TLSHost = s.Host
   444  		}
   445  		// Use http listen limit if https listen limit wasn't defined
   446  		if s.TLSListenLimit == 0 {
   447  			s.TLSListenLimit = s.ListenLimit
   448  		}
   449  		// Use http tcp keep alive if https tcp keep alive wasn't defined
   450  		if int64(s.TLSKeepAlive) == 0 {
   451  			s.TLSKeepAlive = s.KeepAlive
   452  		}
   453  		// Use http read timeout if https read timeout wasn't defined
   454  		if int64(s.TLSReadTimeout) == 0 {
   455  			s.TLSReadTimeout = s.ReadTimeout
   456  		}
   457  		// Use http write timeout if https write timeout wasn't defined
   458  		if int64(s.TLSWriteTimeout) == 0 {
   459  			s.TLSWriteTimeout = s.WriteTimeout
   460  		}
   461  	}
   462  
   463  	if s.hasScheme(schemeUnix) {
   464  		domSockListener, err := net.Listen("unix", string(s.SocketPath))
   465  		if err != nil {
   466  			return err
   467  		}
   468  		s.domainSocketL = domSockListener
   469  	}
   470  
   471  	if s.hasScheme(schemeHTTP) {
   472  		listener, err := net.Listen("tcp", net.JoinHostPort(s.Host, strconv.Itoa(s.Port)))
   473  		if err != nil {
   474  			return err
   475  		}
   476  
   477  		h, p, err := swag.SplitHostPort(listener.Addr().String())
   478  		if err != nil {
   479  			return err
   480  		}
   481  		s.Host = h
   482  		s.Port = p
   483  		s.httpServerL = listener
   484  	}
   485  
   486  	if s.hasScheme(schemeHTTPS) {
   487  		tlsListener, err := net.Listen("tcp", net.JoinHostPort(s.TLSHost, strconv.Itoa(s.TLSPort)))
   488  		if err != nil {
   489  			return err
   490  		}
   491  
   492  		sh, sp, err := swag.SplitHostPort(tlsListener.Addr().String())
   493  		if err != nil {
   494  			return err
   495  		}
   496  		s.TLSHost = sh
   497  		s.TLSPort = sp
   498  		s.httpsServerL = tlsListener
   499  	}
   500  
   501  	s.hasListeners = true
   502  	return nil
   503  }
   504  
   505  // Shutdown server and clean up resources
   506  func (s *Server) Shutdown() error {
   507  	if atomic.CompareAndSwapInt32(&s.shuttingDown, 0, 1) {
   508  		close(s.shutdown)
   509  	}
   510  	return nil
   511  }
   512  
   513  func (s *Server) handleShutdown(wg *sync.WaitGroup, serversPtr *[]*http.Server) {
   514  	// wg.Done must occur last, after s.api.ServerShutdown()
   515  	// (to preserve old behaviour)
   516  	defer wg.Done()
   517  
   518  	<-s.shutdown
   519  
   520  	servers := *serversPtr
   521  
   522  	ctx, cancel := context.WithTimeout(context.TODO(), s.GracefulTimeout)
   523  	defer cancel()
   524  
   525  	// first execute the pre-shutdown hook
   526  	s.api.PreServerShutdown()
   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  }