Files
catalyst/generator/templates/api.gotmpl
2021-12-13 00:39:15 +01:00

125 lines
3.3 KiB
Go Template

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
}