package server import ( "context" "io" "net/http" "git.wzray.com/homelab/hivemind/internal/types" "git.wzray.com/homelab/hivemind/internal/web/middleware" "github.com/rs/zerolog/log" ) type Server struct { mux *http.ServeMux httpServer http.Server } func NewServer(addr string, middleware middleware.Middleware) *Server { mux := http.NewServeMux() s := &Server{ mux: mux, httpServer: http.Server{ Addr: addr, Handler: middleware.Handler(mux), }, } return s } func (s *Server) Listen() error { return s.httpServer.ListenAndServe() } func (s *Server) Shutdown(ctx context.Context) error { return s.httpServer.Shutdown(ctx) } func (s *Server) handleFunc(route types.Route) func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) { log.Debug(). // TODO: make this a middleware Str("method", r.Method). Str("path", r.URL.Path). Str("query", r.URL.RawQuery). Str("remoteAddr", r.RemoteAddr). Send() w.Header().Set("Content-Type", "application/json; charset=utf-8") body, err := io.ReadAll(r.Body) if err != nil { w.Write(fail("read request body: %v", err)) log.Err(err).Msg("unable to read request body") return } raw, err := route.Handle(body) if err != nil { w.Write(fail("handle request: %v", err)) log.Err(err).Msg("unable to handle request") return } data, err := ok(raw) if err != nil { w.Write(fail("marshal response: %v", err)) log.Err(err).Msg("unable to marshal response") return } w.Write(data) } } func (s *Server) Register(endpoint types.Route) { s.mux.HandleFunc(endpoint.Path(), s.handleFunc(endpoint)) } func (s *Server) RegisterRaw(method string, pattern string, handler func(http.ResponseWriter, *http.Request)) { s.mux.HandleFunc(method+" "+pattern, handler) }