diff --git a/handlerApi.go b/handlerApi.go deleted file mode 100644 index 5b3d82a..0000000 --- a/handlerApi.go +++ /dev/null @@ -1,19 +0,0 @@ -package main - -import ( - "log/slog" - "net/http" -) - -func (s *Server) handlerRefresh(w http.ResponseWriter, req *http.Request) { - if req.Header.Get("Authorization") != "Bearer "+s.cfg.Auth.Token { - http.Error(w, "unauthorized", http.StatusInternalServerError) - return - } - if err := s.c.Refresh(); err != nil { - slog.Error("refresh failed", "err", err) - http.Error(w, "refresh failed", http.StatusInternalServerError) - return - } - w.WriteHeader(http.StatusNoContent) -} diff --git a/handlerPkgs.go b/handlerPkgs.go deleted file mode 100644 index 2d63e9f..0000000 --- a/handlerPkgs.go +++ /dev/null @@ -1,54 +0,0 @@ -package main - -import ( - "errors" - "io" - "log/slog" - "net/http" - "path/filepath" - "strconv" - "strings" - - "github.com/ewpt3ch/pkgstash/internal/cache" -) - -func (s *Server) handlePackage(w http.ResponseWriter, req *http.Request) { - - // db files are not signed so we ignore as to not spam mirrors - if strings.HasSuffix(req.PathValue("file"), ".db.sig") { - w.WriteHeader(http.StatusNotFound) - return - } - - // record the useragent from requestor - slog.Debug("Requestors User Agent", "UA", req.Header.Get("User-Agent")) - - // build file paths from the request, they follow archlinux repo - // /[core, extra, etc]/os/[x86_64, arm, etc]/package.pkg.tar.zst[.sig] - repo := req.PathValue("repo") - arch := req.PathValue("arch") - file := req.PathValue("file") - repoPath := filepath.Join(repo, "os", arch, file) //path from mirror root to requested file - - cachedFile, err := s.c.Fetch(repoPath) - if err != nil { - if upstreamErr, ok := errors.AsType[*cache.UpstreamError](err); ok { - slog.Warn("upstream error", "err", upstreamErr.Error()) - http.Error(w, "Not found upstream", upstreamErr.StatusCode) - return - } - slog.Warn("fetch error", "err", err) - http.Error(w, "Failed to fetch from upstream", http.StatusBadGateway) - return - } - defer cachedFile.Reader.Close() - - w.Header().Set("Content-Type", "application/octet-stream") - w.Header().Set("Content-Disposition", "attachment; filename="+cachedFile.Filename) - w.Header().Set("Content-Length", strconv.FormatInt(cachedFile.Size, 10)) - _, err = io.Copy(w, cachedFile.Reader) - if err != nil { - slog.Warn("streaming error", "err", err) - } - -} diff --git a/handler_api.go b/handler_api.go index 6eb55d8..42e8c9c 100644 --- a/handler_api.go +++ b/handler_api.go @@ -1,8 +1,10 @@ package main import ( + "encoding/json" "log/slog" "net/http" + "strings" ) func (s *Server) handlerRefresh(w http.ResponseWriter, req *http.Request) { @@ -10,6 +12,8 @@ func (s *Server) handlerRefresh(w http.ResponseWriter, req *http.Request) { http.Error(w, "unauthorized", http.StatusInternalServerError) return } + defer req.Body.Close() + if err := s.c.Refresh(); err != nil { slog.Error("refresh failed", "err", err) http.Error(w, "refresh failed", http.StatusInternalServerError) @@ -20,8 +24,38 @@ func (s *Server) handlerRefresh(w http.ResponseWriter, req *http.Request) { func (s *Server) handlerLogLevel(w http.ResponseWriter, req *http.Request) { if req.Header.Get("Authorization") != "Bearer "+s.cfg.Auth.Token { - http.Error(w, "unauthorized", http.StatusInternalServerError) + respondWithError(w, http.StatusUnauthorized, "unauthorized") + return + } + defer req.Body.Close() + + type reqParameters struct { + NewLevel string `json:"loglevel"` + } + + decoder := json.NewDecoder(req.Body) + reqParams := reqParameters{} + err := decoder.Decode(&reqParams) + if err != nil { + slog.Debug("json decode erro", "err", err) + respondWithError(w, http.StatusBadRequest, "invalid request") return } + switch strings.ToLower(reqParams.NewLevel) { + case "debug": + s.logLevel.Set(slog.LevelDebug) + case "info": + s.logLevel.Set(slog.LevelInfo) + case "warn": + s.logLevel.Set(slog.LevelWarn) + case "error": + s.logLevel.Set(slog.LevelError) + default: + respondWithError(w, http.StatusBadRequest, "invalid log level") + return + } + + slog.Info("log level changed", "level", reqParams.NewLevel) + w.WriteHeader(http.StatusNoContent) } diff --git a/main.go b/main.go index fb3c764..f2c655d 100644 --- a/main.go +++ b/main.go @@ -11,8 +11,9 @@ import ( ) type Server struct { - cfg *Config - c *cache.Cache + cfg *Config + c *cache.Cache + logLevel *slog.LevelVar } func main() { @@ -29,10 +30,10 @@ func main() { } //set log level from flag if available - var logLevel slog.Level + logLevel := new(slog.LevelVar) if err := logLevel.UnmarshalText([]byte(*logFlag)); err != nil { fmt.Fprintf(os.Stderr, "invalid log level %q, defaulting to INFO\n", *logFlag) - logLevel = slog.LevelInfo + logLevel.Set(slog.LevelInfo) } logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{ @@ -47,11 +48,16 @@ func main() { } c := cache.NewCache(cfg.CacheRoot, cfg.MirrorURLs, cfg.MirroredRepos) - srv := &Server{cfg: cfg, c: c} + srv := &Server{ + cfg: cfg, + c: c, + logLevel: logLevel, + } mux := http.NewServeMux() - mux.HandleFunc("GET /{repo}/os/{arch}/{file}", srv.handlePackage) + mux.HandleFunc("GET /{repo}/os/{arch}/{file}", srv.handlerPackage) mux.HandleFunc("POST /api/refresh", srv.handlerRefresh) + mux.HandleFunc("POST /api/loglevel", srv.handlerLogLevel) if err := srv.c.Refresh(); err != nil { slog.Error("failed to refesh db files", "err", err)