Add HEAD support for rpm repo files (#28309) (#28360)

Backport #28309 by @KN4CK3R

Fixes https://codeberg.org/forgejo/forgejo/issues/1810

zypper uses HEAD requests to check file existence.

https://github.com/openSUSE/libzypp/blob/HEAD/zypp/RepoManager.cc#L2549

https://github.com/openSUSE/libzypp/blob/HEAD/zypp-curl/ng/network/private/downloaderstates/basicdownloader_p.cc#L116

@ExplodingDragon fyi

Co-authored-by: KN4CK3R <admin@oldschoolhack.me>
(cherry picked from commit 5105d2093c)
This commit is contained in:
Giteabot 2023-12-05 16:24:57 +08:00 committed by Earl Warren
parent 171b6a294f
commit ce3a24ef5f
No known key found for this signature in database
GPG key ID: 0579CB2928A78A00
3 changed files with 35 additions and 2 deletions

View file

@ -520,7 +520,10 @@ func CommonRoutes() *web.Route {
r.Get("", rpm.DownloadPackageFile) r.Get("", rpm.DownloadPackageFile)
r.Delete("", reqPackageAccess(perm.AccessModeWrite), rpm.DeletePackageFile) r.Delete("", reqPackageAccess(perm.AccessModeWrite), rpm.DeletePackageFile)
}) })
r.Get("/repodata/{filename}", rpm.GetRepositoryFile) r.Group("/repodata/{filename}", func() {
r.Head("", rpm.CheckRepositoryFileExistence)
r.Get("", rpm.GetRepositoryFile)
})
}, reqPackageAccess(perm.AccessModeRead)) }, reqPackageAccess(perm.AccessModeRead))
r.Group("/rubygems", func() { r.Group("/rubygems", func() {
r.Get("/specs.4.8.gz", rubygems.EnumeratePackages) r.Get("/specs.4.8.gz", rubygems.EnumeratePackages)

View file

@ -57,6 +57,30 @@ func GetRepositoryKey(ctx *context.Context) {
}) })
} }
func CheckRepositoryFileExistence(ctx *context.Context) {
pv, err := rpm_service.GetOrCreateRepositoryVersion(ctx, ctx.Package.Owner.ID)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
pf, err := packages_model.GetFileForVersionByName(ctx, pv.ID, ctx.Params("filename"), packages_model.EmptyFileKey)
if err != nil {
if errors.Is(err, util.ErrNotExist) {
ctx.Status(http.StatusNotFound)
} else {
apiError(ctx, http.StatusInternalServerError, err)
}
return
}
ctx.SetServeHeaders(&context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
ctx.Status(http.StatusOK)
}
// Gets a pre-generated repository metadata file // Gets a pre-generated repository metadata file
func GetRepositoryFile(ctx *context.Context) { func GetRepositoryFile(ctx *context.Context) {
pv, err := rpm_service.GetOrCreateRepositoryVersion(ctx, ctx.Package.Owner.ID) pv, err := rpm_service.GetOrCreateRepositoryVersion(ctx, ctx.Package.Owner.ID)

View file

@ -149,12 +149,18 @@ gpgkey=%sapi/packages/%s/rpm/repository.key`, user.Name, user.Name, setting.AppN
url := rootURL + "/repodata" url := rootURL + "/repodata"
req := NewRequest(t, "GET", url+"/dummy.xml") req := NewRequest(t, "HEAD", url+"/dummy.xml")
MakeRequest(t, req, http.StatusNotFound)
req = NewRequest(t, "GET", url+"/dummy.xml")
MakeRequest(t, req, http.StatusNotFound) MakeRequest(t, req, http.StatusNotFound)
t.Run("repomd.xml", func(t *testing.T) { t.Run("repomd.xml", func(t *testing.T) {
defer tests.PrintCurrentTest(t)() defer tests.PrintCurrentTest(t)()
req = NewRequest(t, "HEAD", url+"/repomd.xml")
MakeRequest(t, req, http.StatusOK)
req = NewRequest(t, "GET", url+"/repomd.xml") req = NewRequest(t, "GET", url+"/repomd.xml")
resp := MakeRequest(t, req, http.StatusOK) resp := MakeRequest(t, req, http.StatusOK)