diff --git a/TODO.md b/TODO.md index 1c6f096..c270cb8 100644 --- a/TODO.md +++ b/TODO.md @@ -1,6 +1,6 @@ - Add better logging for errors, filename more deatail - ~package main~ - - internal/cache + - ~internal/cache~ - api endpoint to change level - implement streaming diff --git a/handler_api.go b/handler_api.go new file mode 100644 index 0000000..6eb55d8 --- /dev/null +++ b/handler_api.go @@ -0,0 +1,27 @@ +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) +} + +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) + return + } + +} diff --git a/handler_pkgs.go b/handler_pkgs.go new file mode 100644 index 0000000..2d63e9f --- /dev/null +++ b/handler_pkgs.go @@ -0,0 +1,54 @@ +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) + } + +}