1 Star 0 Fork 0

gaogaoss/go-swagger

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
server.go 7.29 KB
一键复制 编辑 原始数据 按行查看 历史
gaogao 提交于 2024-07-30 09:49 . first commit
package restapi
import (
"crypto/tls"
"log"
"net"
"net/http"
"os"
"strconv"
"sync"
"time"
"github.com/go-openapi/swag"
flags "github.com/jessevdk/go-flags"
graceful "github.com/tylerb/graceful"
"github.com/go-swagger/go-swagger/examples/tutorials/todo-list/server-complete/restapi/operations"
)
const (
schemeHTTP = "http"
schemeHTTPS = "https"
schemeUnix = "unix"
)
var defaultSchemes []string
func init() {
defaultSchemes = []string{
schemeHTTP,
}
}
// NewServer creates a new api todo list server but does not configure it
func NewServer(api *operations.TodoListAPI) *Server {
s := new(Server)
s.api = api
return s
}
// ConfigureAPI configures the API and handlers. Needs to be called before Serve
func (s *Server) ConfigureAPI() {
if s.api != nil {
s.handler = configureAPI(s.api)
}
}
// ConfigureFlags configures the additional flags defined by the handlers. Needs to be called before the parser.Parse
func (s *Server) ConfigureFlags() {
if s.api != nil {
configureFlags(s.api)
}
}
// Server for the todo list API
type Server struct {
EnabledListeners []string `long:"scheme" description:"the listeners to enable, this can be repeated and defaults to the schemes in the swagger spec"`
SocketPath flags.Filename `long:"socket-path" description:"the unix socket to listen on" default:"/var/run/todo-list.sock"`
domainSocketL net.Listener
Host string `long:"host" description:"the IP to listen on" default:"localhost" env:"HOST"`
Port int `long:"port" description:"the port to listen on for insecure connections, defaults to a random value" env:"PORT"`
httpServerL net.Listener
TLSHost string `long:"tls-host" description:"the IP to listen on for tls, when not specified it's the same as --host" env:"TLS_HOST"`
TLSPort int `long:"tls-port" description:"the port to listen on for secure connections, defaults to a random value" env:"TLS_PORT"`
TLSCertificate flags.Filename `long:"tls-certificate" description:"the certificate to use for secure connections" env:"TLS_CERTIFICATE"`
TLSCertificateKey flags.Filename `long:"tls-key" description:"the private key to use for secure conections" env:"TLS_PRIVATE_KEY"`
httpsServerL net.Listener
api *operations.TodoListAPI
handler http.Handler
hasListeners bool
}
// Logf logs message either via defined user logger or via system one if no user logger is defined.
func (s *Server) Logf(f string, args ...interface{}) {
if s.api != nil && s.api.Logger != nil {
s.api.Logger(f, args...)
} else {
log.Printf(f, args...)
}
}
// Fatalf logs message either via defined user logger or via system one if no user logger is defined.
// Exits with non-zero status after printing
func (s *Server) Fatalf(f string, args ...interface{}) {
if s.api != nil && s.api.Logger != nil {
s.api.Logger(f, args...)
os.Exit(1)
} else {
log.Fatalf(f, args...)
}
}
// SetAPI configures the server with the specified API. Needs to be called before Serve
func (s *Server) SetAPI(api *operations.TodoListAPI) {
if api == nil {
s.api = nil
s.handler = nil
return
}
s.api = api
s.api.Logger = log.Printf
s.handler = configureAPI(api)
}
func (s *Server) hasScheme(scheme string) bool {
schemes := s.EnabledListeners
if len(schemes) == 0 {
schemes = defaultSchemes
}
for _, v := range schemes {
if v == scheme {
return true
}
}
return false
}
// Serve the api
func (s *Server) Serve() (err error) {
if !s.hasListeners {
if err := s.Listen(); err != nil {
return err
}
}
var wg sync.WaitGroup
if s.hasScheme(schemeUnix) {
domainSocket := &graceful.Server{Server: new(http.Server)}
domainSocket.Handler = s.handler
wg.Add(1)
s.Logf("Serving todo list at unix://%s", s.SocketPath)
go func(l net.Listener) {
defer wg.Done()
if err := domainSocket.Serve(l); err != nil {
s.Fatalf("%v", err)
}
s.Logf("Stopped serving todo list at unix://%s", s.SocketPath)
}(s.domainSocketL)
}
if s.hasScheme(schemeHTTP) {
httpServer := &graceful.Server{Server: new(http.Server)}
httpServer.SetKeepAlivesEnabled(true)
httpServer.TCPKeepAlive = 3 * time.Minute
httpServer.Handler = s.handler
wg.Add(1)
s.Logf("Serving todo list at http://%s", s.httpServerL.Addr())
go func(l net.Listener) {
defer wg.Done()
if err := httpServer.Serve(l); err != nil {
s.Fatalf("%v", err)
}
s.Logf("Stopped serving todo list at http://%s", l.Addr())
}(s.httpServerL)
}
if s.hasScheme(schemeHTTPS) {
httpsServer := &graceful.Server{Server: new(http.Server)}
httpsServer.SetKeepAlivesEnabled(true)
httpsServer.TCPKeepAlive = 3 * time.Minute
httpsServer.Handler = s.handler
httpsServer.TLSConfig = new(tls.Config)
httpsServer.TLSConfig.NextProtos = []string{"http/1.1"}
// https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_Sheet#Rule_-_Only_Support_Strong_Protocols
httpsServer.TLSConfig.MinVersion = tls.VersionTLS12
httpsServer.TLSConfig.Certificates = make([]tls.Certificate, 1)
httpsServer.TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(string(s.TLSCertificate), string(s.TLSCertificateKey))
configureTLS(httpsServer.TLSConfig)
if err != nil {
return err
}
wg.Add(1)
s.Logf("Serving todo list at https://%s", s.httpsServerL.Addr())
go func(l net.Listener) {
defer wg.Done()
if err := httpsServer.Serve(l); err != nil {
s.Fatalf("%v", err)
}
s.Logf("Stopped serving todo list at https://%s", l.Addr())
}(tls.NewListener(s.httpsServerL, httpsServer.TLSConfig))
}
wg.Wait()
return nil
}
// Listen creates the listeners for the server
func (s *Server) Listen() error {
if s.hasListeners { // already done this
return nil
}
if s.hasScheme(schemeHTTPS) { // exit early on missing params
if s.TLSCertificate == "" {
if s.TLSCertificateKey == "" {
s.Fatalf("the required flags `--tls-certificate` and `--tls-key` were not specified")
}
s.Fatalf("the required flag `--tls-certificate` was not specified")
}
if s.TLSCertificateKey == "" {
s.Fatalf("the required flag `--tls-key` was not specified")
}
// Use http host if https host wasn't defined
if s.TLSHost == "" {
s.TLSHost = s.Host
}
}
if s.hasScheme(schemeUnix) {
domSockListener, err := net.Listen("unix", string(s.SocketPath))
if err != nil {
return err
}
s.domainSocketL = domSockListener
}
if s.hasScheme(schemeHTTP) {
listener, err := net.Listen("tcp", net.JoinHostPort(s.Host, strconv.Itoa(s.Port)))
if err != nil {
return err
}
h, p, err := swag.SplitHostPort(listener.Addr().String())
if err != nil {
return err
}
s.Host = h
s.Port = p
s.httpServerL = listener
}
if s.hasScheme(schemeHTTPS) {
tlsListener, err := net.Listen("tcp", net.JoinHostPort(s.TLSHost, strconv.Itoa(s.TLSPort)))
if err != nil {
return err
}
sh, sp, err := swag.SplitHostPort(tlsListener.Addr().String())
if err != nil {
return err
}
s.TLSHost = sh
s.TLSPort = sp
s.httpsServerL = tlsListener
}
s.hasListeners = true
return nil
}
// Shutdown server and clean up resources
func (s *Server) Shutdown() error {
s.api.ServerShutdown()
return nil
}
// GetHandler returns a handler useful for testing
func (s *Server) GetHandler() http.Handler {
return s.handler
}
// SetHandler allows for setting a http handler on this server
func (s *Server) SetHandler(handler http.Handler) {
s.handler = handler
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/gaogaoss/go-swagger.git
git@gitee.com:gaogaoss/go-swagger.git
gaogaoss
go-swagger
go-swagger
da1ca328b83f

搜索帮助