package {{ .APIPackage }} import ( "context" "log" "net/http" "os" "os/signal" "syscall" "time" "strings" "golang.org/x/oauth2" "github.com/gin-gonic/gin" {{range .DefaultImports}}{{printf "%q" .}} {{end}} {{range $key, $value := .Imports}}{{$key}} {{ printf "%q" $value}} {{end}} "github.com/SecurityBrewery/catalyst/generated/restapi/api" "github.com/SecurityBrewery/catalyst/role" ) // Service is the interface that must be implemented in order to provide // business logic for the Server service. type Service interface { {{range .Operations}}{{ pascalize .Name }}(ctx context.Context{{ if .Params }}, params *{{.Package}}.{{ pascalize .Name }}Params{{ end }}) *api.Response {{end}} } // Config defines the config options for the API server. type Config struct { Address string InsecureHTTP bool TLSCertFile string TLSKeyFile string } // Server defines the Server service. type Server struct { *gin.Engine config *Config server *http.Server service Service {{ range .Operations | basePaths }}{{ . | export }}Group *gin.RouterGroup {{end}} RoleAuth func([]role.Role) gin.HandlerFunc } // New initializes a new Server service. func New(svc Service, config *Config) *Server { engine := gin.New() engine.Use(gin.Recovery()) return &Server{ Engine: engine, service: svc, config: config, server: &http.Server{ Addr: config.Address, Handler: engine, ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, }, {{range .Operations | basePaths }}{{ . | export }}Group: engine.Group("/{{.}}"), {{end}} RoleAuth: func(i []role.Role) gin.HandlerFunc { return func(c *gin.Context) { c.Next() } }, } } // ConfigureRoutes configures the routes for the Server service. // Configuring of routes includes setting up Auth if it is enabled. func (s *Server) ConfigureRoutes() { {{range .Operations}}s.{{ slice .BasePath 1 | export }}Group.{{.Method}}({{ .Path | ginizePath | printf "%q" }}, s.RoleAuth([]role.Role{ {{ .SecurityRequirements | roles }} }), {{.Package}}.{{ pascalize .Name }}Endpoint(s.service.{{ pascalize .Name }})) {{end}}} // run the Server. It will listen on either HTTP or HTTPS depending on the // config passed to NewServer. func (s *Server) run() error { log.Printf("Serving on address %s\n", s.server.Addr) if s.config.InsecureHTTP { return s.server.ListenAndServe() } return s.server.ListenAndServeTLS(s.config.TLSCertFile, s.config.TLSKeyFile) } // Shutdown will gracefully shutdown the Server. func (s *Server) Shutdown() error { return s.server.Shutdown(context.Background()) } // RunWithSigHandler runs the Server with SIGTERM handling automatically // enabled. The server will listen for a SIGTERM signal and gracefully shutdown // the web server. // It's possible to optionally pass any number shutdown functions which will // execute one by one after the webserver has been shutdown successfully. func (s *Server) RunWithSigHandler(shutdown ...func() error) error { sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM) go func() { <-sigCh s.Shutdown() }() err := s.run() if err != nil { if err != http.ErrServerClosed { return err } } for _, fn := range shutdown { err := fn() if err != nil { return err } } return nil }