121 lines
2.8 KiB
Go
121 lines
2.8 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
"time"
|
|
|
|
fiberzap "github.com/gofiber/contrib/fiberzap/v2"
|
|
"github.com/gofiber/contrib/swagger"
|
|
"github.com/gofiber/fiber/v2"
|
|
middleware "github.com/oapi-codegen/fiber-middleware"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
type Server struct {
|
|
port int
|
|
logger *zap.Logger
|
|
apiHandlers *APIHandlers
|
|
pool *pgxpool.Pool
|
|
}
|
|
|
|
func NewServer(apiHandlers *APIHandlers, port int, logger *zap.Logger, pool *pgxpool.Pool) *Server {
|
|
return &Server{
|
|
apiHandlers: apiHandlers,
|
|
port: port,
|
|
logger: logger,
|
|
pool: pool,
|
|
}
|
|
}
|
|
|
|
func (s *Server) Run(ctx context.Context) {
|
|
middlewares := make([]fiber.Handler, 0)
|
|
|
|
loggingMiddleware := fiberzap.New(fiberzap.Config{
|
|
Logger: s.logger,
|
|
})
|
|
middlewares = append(middlewares, loggingMiddleware)
|
|
|
|
app := setupServer(s.apiHandlers, middlewares, s.logger, false)
|
|
|
|
go func() {
|
|
fiberErr := app.Listen(fmt.Sprintf(":%d", s.port))
|
|
if fiberErr != nil {
|
|
panic(fiberErr)
|
|
}
|
|
}()
|
|
|
|
s.logger.Info("HTTP server is now running", zap.Int("port", s.port))
|
|
|
|
<-ctx.Done()
|
|
shutdownBegan := time.Now()
|
|
|
|
s.logger.Info("Shutting HTTP server down gracefully...")
|
|
err := app.ShutdownWithTimeout(10 * time.Second)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// gracefully shutdown/close database pool
|
|
if s.pool != nil {
|
|
s.pool.Close()
|
|
}
|
|
|
|
s.logger.Info("HTTP server shut down gracefully.", zap.Duration("duration", time.Since(shutdownBegan)))
|
|
}
|
|
|
|
func NewTestingServer(apiHandlers *APIHandlers) *fiber.App {
|
|
return setupServer(apiHandlers, nil, zap.NewNop(), true)
|
|
}
|
|
|
|
func setupServer(apiHandlers *APIHandlers, middlewares []fiber.Handler, logger *zap.Logger, testing bool) *fiber.App {
|
|
config := fiber.Config{
|
|
DisableStartupMessage: true,
|
|
|
|
IdleTimeout: 10 * time.Second,
|
|
ReadTimeout: 10 * time.Second,
|
|
WriteTimeout: 10 * time.Second,
|
|
}
|
|
|
|
app := fiber.New(config)
|
|
|
|
for _, mw := range middlewares {
|
|
app.Use(mw)
|
|
}
|
|
|
|
swaggerConfig := swagger.Config{
|
|
BasePath: "/",
|
|
FilePath: "./api/v1/openapi.yaml",
|
|
Path: "/swagger",
|
|
Title: "Swagger API Docs",
|
|
}
|
|
|
|
if testing {
|
|
swaggerConfig = swagger.Config{
|
|
BasePath: "/",
|
|
FilePath: "../../api/v1/openapi.yaml",
|
|
Path: "/swagger",
|
|
Title: "Swagger API Docs",
|
|
}
|
|
}
|
|
|
|
app.Use(swagger.New(swaggerConfig))
|
|
|
|
serverSwaggerSpec, err := GetSwagger()
|
|
if err != nil {
|
|
logger.Fatal("Error getting swagger", zap.Error(err))
|
|
}
|
|
|
|
// See: https://github.com/deepmap/oapi-codegen/blob/master/examples/petstore-expanded/fiber/petstore.go#L41
|
|
// Clear out the servers array in the swagger spec, that skips validating
|
|
// that server names match. We don't know how this thing will be run.
|
|
serverSwaggerSpec.Servers = nil
|
|
|
|
app.Use(middleware.OapiRequestValidator(serverSwaggerSpec))
|
|
|
|
handlers := NewStrictHandler(apiHandlers, nil)
|
|
RegisterHandlers(app, handlers)
|
|
|
|
return app
|
|
}
|