package server import ( "context" "log/slog" "strings" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" "github.com/memohai/memoh/internal/auth" ) type Server struct { echo *echo.Echo addr string logger *slog.Logger } type Handler interface { Register(e *echo.Echo) } func NewServer(log *slog.Logger, addr string, jwtSecret string, handlers ...Handler, ) *Server { if addr == "" { addr = ":8080" } e := echo.New() e.HideBanner = true e.Use(middleware.Recover()) e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{ LogStatus: true, LogURI: true, LogMethod: true, LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error { log.Info("request", slog.String("method", v.Method), slog.String("uri", v.URI), slog.Int("status", v.Status), slog.Duration("latency", v.Latency), slog.String("remote_ip", c.RealIP()), ) return nil }, })) e.Use(auth.JWTMiddleware(jwtSecret, func(c echo.Context) bool { path := c.Request().URL.Path if path == "/ping" || path == "/health" || path == "/api/swagger.json" || path == "/auth/login" { return true } if strings.HasPrefix(path, "/api/docs") { return true } return false })) for _, h := range handlers { if h != nil { h.Register(e) } } return &Server{ echo: e, addr: addr, logger: log.With(slog.String("component", "server")), } } func (s *Server) Start() error { return s.echo.Start(s.addr) } func (s *Server) Stop(ctx context.Context) error { return s.echo.Shutdown(ctx) }