package api import ( "net/http" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "github.com/inou-ai/messaging-center/internal/core" "github.com/inou-ai/messaging-center/internal/store" ) // Server is the HTTP API server. type Server struct { config *core.Config store *store.Store oauth *OAuthProvider router chi.Router } // NewServer creates a new API server. func NewServer(cfg *core.Config, s *store.Store) *Server { srv := &Server{ config: cfg, store: s, oauth: NewOAuthProvider(&cfg.OAuth), } srv.setupRoutes() return srv } // ServeHTTP implements http.Handler. func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { s.router.ServeHTTP(w, r) } func (s *Server) setupRoutes() { r := chi.NewRouter() // Middleware r.Use(middleware.Logger) r.Use(middleware.Recoverer) r.Use(middleware.RealIP) // Health endpoints (no auth) r.Get("/health", s.handleHealth) r.Get("/ready", s.handleReady) // OAuth token endpoint r.Post("/oauth/token", s.oauth.HandleToken) // API v1 r.Route("/api/v1", func(r chi.Router) { // Messages r.Route("/messages", func(r chi.Router) { r.With(s.oauth.RequireAuth("messages:read")).Get("/", s.handleListMessages) r.With(s.oauth.RequireAuth("messages:read")).Get("/{id}", s.handleGetMessage) r.With(s.oauth.RequireAuth("messages:write")).Post("/", s.handleCreateMessage) }) // Commands r.Route("/commands", func(r chi.Router) { r.With(s.oauth.RequireAuth("commands:write")).Post("/", s.handleCreateCommand) r.With(s.oauth.RequireAuth("commands:write")).Get("/{id}", s.handleGetCommand) }) // Channels r.Route("/channels", func(r chi.Router) { r.With(s.oauth.RequireAuth("admin")).Get("/", s.handleListChannels) }) }) s.router = r } // handleHealth returns 200 OK if the server is running. func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) { writeJSON(w, http.StatusOK, map[string]string{"status": "ok"}) } // handleReady returns 200 OK if the server is ready to accept traffic. func (s *Server) handleReady(w http.ResponseWriter, r *http.Request) { if err := s.store.Ping(); err != nil { writeJSON(w, http.StatusServiceUnavailable, map[string]string{ "status": "not ready", "error": err.Error(), }) return } writeJSON(w, http.StatusOK, map[string]string{"status": "ready"}) }