package gitrpc import ( "errors" "io" "net/http" ) func (s *Server) authorizeRead(w http.ResponseWriter, r *http.Request, repo string) bool { if repo == "" { http.Error(w, "missing repo", http.StatusBadRequest) return false } // No local JWT/JWKS check: /raw, /archive, /patch are reached only via the // console gateway (which authenticates the user) or internally. smart-HTTP // clone/push auth lives in the daemon App (PAT-based), not here. return true } func (s *Server) serveRaw(w http.ResponseWriter, r *http.Request) { q := r.URL.Query() repoName := q.Get("repo") if !s.authorizeRead(w, r, repoName) { return } ref := q.Get("ref") filePath := q.Get("file") repo, err := s.open(r.Context(), repoName) if err != nil { writeHTTPError(w, err) return } content, err := repo.GetRawContent(ref, filePath) if err != nil { http.Error(w, "read file: "+err.Error(), http.StatusNotFound) return } w.Header().Set("Content-Type", "application/octet-stream") _, _ = io.WriteString(w, content) } func (s *Server) servePatch(w http.ResponseWriter, r *http.Request) { q := r.URL.Query() repoName := q.Get("repo") if !s.authorizeRead(w, r, repoName) { return } sha := q.Get("sha") repo, err := s.open(r.Context(), repoName) if err != nil { writeHTTPError(w, err) return } patch, err := repo.Patch(sha) if err != nil { http.Error(w, "format-patch: "+err.Error(), http.StatusNotFound) return } w.Header().Set("Content-Type", "text/plain; charset=utf-8") _, _ = io.WriteString(w, patch) } func (s *Server) serveArchive(w http.ResponseWriter, r *http.Request) { q := r.URL.Query() repoName := q.Get("repo") if !s.authorizeRead(w, r, repoName) { return } ref := q.Get("ref") format := q.Get("format") repo, err := s.open(r.Context(), repoName) if err != nil { writeHTTPError(w, err) return } if format == "" { format = "zip" } switch format { case "zip": w.Header().Set("Content-Type", "application/zip") case "tar": w.Header().Set("Content-Type", "application/x-tar") default: http.Error(w, "format must be zip or tar", http.StatusBadRequest) return } if err := repo.Archive(ref, format, w); err != nil { http.Error(w, "archive: "+err.Error(), http.StatusInternalServerError) return } } func writeHTTPError(w http.ResponseWriter, err error) { var re *rpcError if errors.As(err, &re) { switch re.Code { case codeRepoNotFound: http.Error(w, re.Message, http.StatusNotFound) default: http.Error(w, re.Message, http.StatusBadRequest) } return } http.Error(w, err.Error(), http.StatusBadRequest) }