package daemon import ( "context" "fmt" "log/slog" "net/http" service "spud/service" "strconv" ) type Daemon struct { Host string Port int Services service.ServiceClient Routes map[string]http.HandlerFunc } type HandlerFuncWithContext = func(w http.ResponseWriter, r *http.Request, c context.Context) type RecordingResponseWriter struct { responseWriter http.ResponseWriter StatusCode int } func (r *RecordingResponseWriter) WriteHeader(statusCode int) { r.StatusCode = statusCode r.responseWriter.WriteHeader(statusCode) } func (r RecordingResponseWriter) Write(b []byte) (int, error) { return r.responseWriter.Write(b) } func (r RecordingResponseWriter) Header() http.Header { return r.responseWriter.Header() } func handleFuncWithContext(h HandlerFuncWithContext, c context.Context) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { respWriter := &RecordingResponseWriter{responseWriter: w} h(respWriter, r, c) slog.Info("Request", "Method", r.Method, "Path", r.URL.Path, "Status", strconv.Itoa(respWriter.StatusCode)) } } func NewDaemon(host string, port int, serviceClient service.ServiceClient) *Daemon { d := &Daemon{Host: host, Port: port} if serviceClient == nil { d.Services = service.NewPodmanServiceManager() } else { d.Services = serviceClient } return d } func (d Daemon) GetListenAddress() string { return fmt.Sprintf("%s:%d", d.Host, d.Port) } func (d Daemon) Start() { daemonContext := context.WithValue(context.Background(), "client", d.Services) for route, handler := range GetApiRoutes() { http.HandleFunc(route, handleFuncWithContext(handler, daemonContext)) } http.ListenAndServe(d.GetListenAddress(), nil) }