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>tags/v1.21.2
@@ -520,7 +520,10 @@ func CommonRoutes() *web.Route { | |||
r.Get("", rpm.DownloadPackageFile) | |||
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)) | |||
r.Group("/rubygems", func() { | |||
r.Get("/specs.4.8.gz", rubygems.EnumeratePackages) |
@@ -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 | |||
func GetRepositoryFile(ctx *context.Context) { | |||
pv, err := rpm_service.GetOrCreateRepositoryVersion(ctx, ctx.Package.Owner.ID) |
@@ -149,12 +149,18 @@ gpgkey=%sapi/packages/%s/rpm/repository.key`, user.Name, user.Name, setting.AppN | |||
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) | |||
t.Run("repomd.xml", func(t *testing.T) { | |||
defer tests.PrintCurrentTest(t)() | |||
req = NewRequest(t, "HEAD", url+"/repomd.xml") | |||
MakeRequest(t, req, http.StatusOK) | |||
req = NewRequest(t, "GET", url+"/repomd.xml") | |||
resp := MakeRequest(t, req, http.StatusOK) | |||