github.com/looshlee/beatles@v0.0.0-20220727174639-742810ab631c/api/v1/server.gotmpl (about)

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