// Copyright (C) 2023 Marius Schellenberger package api import ( "context" "net" "net/http" "time" "git.giftfish.de/ston1th/keyctl/pkg/api/types" serverv1 "git.giftfish.de/ston1th/keyctl/pkg/api/v1/server" "git.giftfish.de/ston1th/keyctl/pkg/db" "github.com/go-logr/logr" "github.com/gorilla/mux" ) // Server is the webapp and api server type Server struct { srv *http.Server mux *mux.Router log logr.Logger Data *types.ContextData listen net.Listener } type notFoundHandler struct { s *Server } func (nf *notFoundHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { types.NewContext(w, r, nf.s.Data, nf.s.log).Err(types.ErrInvalidAPIRoute) } // NewHTTPServer returns a new HTTPServer func NewServer(log logr.Logger, listen string) (*Server, error) { s := &Server{ mux: mux.NewRouter(), log: log, Data: &types.ContextData{Approver: types.NewApprover()}, } l, err := net.Listen("tcp", listen) if err != nil { return nil, err } s.listen = l s.mux.NotFoundHandler = ¬FoundHandler{s} for _, v := range serverv1.Routes { s.mux.HandleFunc(v.Path, s.contextWrapper(v.Handler)).Methods(v.Methods...) } return s, nil } func (s *Server) Start(db *db.DB) { s.srv = &http.Server{ Handler: s.mux, ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, } s.Data.DB = db go func() { err := s.srv.Serve(s.listen) if err != nil && err != http.ErrServerClosed { s.log.Error(err, "") } }() return } func (s *Server) contextWrapper(h types.CtxHandler) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { h(types.NewContext(w, r, s.Data, s.log)) } } // Stop stops listening for incoming connections and closes currently open connections func (s *Server) Shutdown(ctx context.Context) { s.log.Info("stopping") err := s.srv.Shutdown(ctx) if err != nil { s.log.Error(err, "") } s.log.Info("stopped") }