Skip to content
Snippets Groups Projects
serve.go 2.05 KiB
Newer Older
package cmd

import (
	"net/http"

	"github.com/justinas/alice"
	"github.com/rs/zerolog"
	"orus.io/orus-io/go-orusapi"
	"orus.io/orus-io/go-orusapi/auth"
//nolint:lll
type ServeCmd[E any] struct {
	Server *orusapi.Server

	AutoMigrate bool `long:"auto-migrate" ini-name:"auto-migrate" description:"Automaticaly migrate the database if necessary" env:"AUTOMIGRATE"`
}

type serveAPI struct {
	name    string
	handler http.Handler
}

func (api *serveAPI) Name() string {
	return api.name
}

func (api *serveAPI) Handler() http.Handler {
	return api.handler
}

func (api *serveAPI) PreServerShutdown() {
}

func (api *serveAPI) ServerShutdown() {
}

func (cmd *ServeCmd[E]) Execute([]string) error {
	if err := cmd.program.EnsureDB(cmd.AutoMigrate); err != nil {
		return err
	}

	defer cmd.program.CloseDB()

	stack := alice.New(orusapi.LogStack(cmd.program.Logger, zerolog.WarnLevel)...)
	for _, middleware := range cmd.program.authMiddlewares {
		m, err := middleware.Middleware(cmd.program)
	stack = stack.Append(auth.LogUserHandler)
	for _, middleware := range cmd.program.middlewares {
		m, err := middleware.Middleware(cmd.program)
		if err != nil {
			return err
		}
		stack = stack.Append(m)
	}

	handler := stack.Then(cmd.program.setupHandler(cmd.program))
	cmd.Server.SetLog(cmd.program.Logger)
	cmd.Server.Environment = cmd.program.InfoOptions.Environment
	cmd.Server.SetAPI(&serveAPI{
		name:    cmd.program.Parser.Name,
		handler: handler,
	})

	defer func() {
		if err := cmd.Server.Shutdown(); err != nil {
			cmd.program.Logger.Err(err).Msg("error shutting down the server")
		}
	}()

	if err := cmd.Server.Serve(); err != nil {
		return err
	}

	return nil
}

func SetupServeCmd[E any](program *Program[E]) *ServeCmd[E] {
	cmd := ServeCmd[E]{
		program: program,
		Server:  orusapi.NewServer(nil),
	}

	serve, err := program.Parser.AddCommand("serve", "Serves the API", "", &cmd)
	if err != nil {
		program.Logger.Fatal().Msg(err.Error())
	}
	serve.EnvNamespace = "SERVE"

	return &cmd
}