package handlers import ( "fmt" "net/http" "xorm.io/xorm" gitdomain "github.com/forgeo/forgebucket/internal/domain/git" ) type ArchiveHandler struct { db *xorm.Engine } func NewArchiveHandler(db *xorm.Engine) *ArchiveHandler { return &ArchiveHandler{db: db} } var archiveFormats = map[string]struct { contentType string ext string }{ "zip": {"application/zip", "zip"}, "tar.gz": {"application/x-tar", "tar.gz"}, "bundle": {"application/octet-stream", "bundle"}, } func (h *ArchiveHandler) Download(w http.ResponseWriter, r *http.Request) { repo, ok := resolveRepo(h.db, w, r) if !ok { return } format := r.URL.Query().Get("format") if format == "" { format = "zip" } meta, allowed := archiveFormats[format] if !allowed { jsonError(w, "format must be zip, tar.gz, or bundle", http.StatusBadRequest) return } ref := r.URL.Query().Get("ref") if ref == "" { ref = repo.DefaultBranch } if ref == "" { ref = "HEAD" } filename := fmt.Sprintf("%s-%s.%s", repo.Name, ref, meta.ext) w.Header().Set("Content-Type", meta.contentType) w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, filename)) if err := gitdomain.ArchiveStream(repo.DiskPath, ref, format, w); err != nil { // Headers already written — can't change status code; just log and close. _ = err } }