mirror of
https://codeberg.org/forgejo/forgejo
synced 2024-11-24 02:36:10 +01:00
Backport (#21568) This PR fixes issue #21567 allowing for package tarball URLs to match the upstream registry (and GitLab/JFrog Artifactory URLs). It uses a regex to parse the filename (which contains the NPM version) and does a fuzzy search to pull it out. The regex was built/expanded from http://json.schemastore.org/package, https://github.com/Masterminds/semver, and https://docs.npmjs.com/cli/v6/using-npm/semver and is testable here: https://regex101.com/r/OydBJq/5 Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
This commit is contained in:
parent
14342047ad
commit
995ae06a6e
|
@ -123,10 +123,16 @@ func TestPackageNpm(t *testing.T) {
|
||||||
b, _ := base64.StdEncoding.DecodeString(data)
|
b, _ := base64.StdEncoding.DecodeString(data)
|
||||||
assert.Equal(t, b, resp.Body.Bytes())
|
assert.Equal(t, b, resp.Body.Bytes())
|
||||||
|
|
||||||
|
req = NewRequest(t, "GET", fmt.Sprintf("%s/-/%s", root, filename))
|
||||||
|
req = addTokenAuthHeader(req, token)
|
||||||
|
resp = MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
|
assert.Equal(t, b, resp.Body.Bytes())
|
||||||
|
|
||||||
pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeNpm)
|
pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeNpm)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, pvs, 1)
|
assert.Len(t, pvs, 1)
|
||||||
assert.Equal(t, int64(1), pvs[0].DownloadCount)
|
assert.Equal(t, int64(2), pvs[0].DownloadCount)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("PackageMetadata", func(t *testing.T) {
|
t.Run("PackageMetadata", func(t *testing.T) {
|
||||||
|
|
|
@ -199,11 +199,13 @@ func Routes() *web.Route {
|
||||||
r.Get("", npm.PackageMetadata)
|
r.Get("", npm.PackageMetadata)
|
||||||
r.Put("", reqPackageAccess(perm.AccessModeWrite), npm.UploadPackage)
|
r.Put("", reqPackageAccess(perm.AccessModeWrite), npm.UploadPackage)
|
||||||
r.Get("/-/{version}/{filename}", npm.DownloadPackageFile)
|
r.Get("/-/{version}/{filename}", npm.DownloadPackageFile)
|
||||||
|
r.Get("/-/{filename}", npm.DownloadPackageFileByName)
|
||||||
})
|
})
|
||||||
r.Group("/{id}", func() {
|
r.Group("/{id}", func() {
|
||||||
r.Get("", npm.PackageMetadata)
|
r.Get("", npm.PackageMetadata)
|
||||||
r.Put("", reqPackageAccess(perm.AccessModeWrite), npm.UploadPackage)
|
r.Put("", reqPackageAccess(perm.AccessModeWrite), npm.UploadPackage)
|
||||||
r.Get("/-/{version}/{filename}", npm.DownloadPackageFile)
|
r.Get("/-/{version}/{filename}", npm.DownloadPackageFile)
|
||||||
|
r.Get("/-/{filename}", npm.DownloadPackageFileByName)
|
||||||
})
|
})
|
||||||
r.Group("/-/package/@{scope}/{id}/dist-tags", func() {
|
r.Group("/-/package/@{scope}/{id}/dist-tags", func() {
|
||||||
r.Get("", npm.ListPackageTags)
|
r.Get("", npm.ListPackageTags)
|
||||||
|
|
|
@ -105,6 +105,49 @@ func DownloadPackageFile(ctx *context.Context) {
|
||||||
ctx.ServeStream(s, pf.Name)
|
ctx.ServeStream(s, pf.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DownloadPackageFileByName finds the version and serves the contents of a package
|
||||||
|
func DownloadPackageFileByName(ctx *context.Context) {
|
||||||
|
filename := ctx.Params("filename")
|
||||||
|
|
||||||
|
pvs, _, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
|
||||||
|
OwnerID: ctx.Package.Owner.ID,
|
||||||
|
Type: packages_model.TypeNpm,
|
||||||
|
Name: packages_model.SearchValue{
|
||||||
|
ExactMatch: true,
|
||||||
|
Value: packageNameFromParams(ctx),
|
||||||
|
},
|
||||||
|
HasFileWithName: filename,
|
||||||
|
IsInternal: false,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
apiError(ctx, http.StatusInternalServerError, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(pvs) != 1 {
|
||||||
|
apiError(ctx, http.StatusNotFound, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s, pf, err := packages_service.GetFileStreamByPackageVersion(
|
||||||
|
ctx,
|
||||||
|
pvs[0],
|
||||||
|
&packages_service.PackageFileInfo{
|
||||||
|
Filename: filename,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
if err == packages_model.ErrPackageFileNotExist {
|
||||||
|
apiError(ctx, http.StatusNotFound, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
apiError(ctx, http.StatusInternalServerError, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer s.Close()
|
||||||
|
|
||||||
|
ctx.ServeStream(s, pf.Name)
|
||||||
|
}
|
||||||
|
|
||||||
// UploadPackage creates a new package
|
// UploadPackage creates a new package
|
||||||
func UploadPackage(ctx *context.Context) {
|
func UploadPackage(ctx *context.Context) {
|
||||||
npmPackage, err := npm_module.ParsePackage(ctx.Req.Body)
|
npmPackage, err := npm_module.ParsePackage(ctx.Req.Body)
|
||||||
|
|
Loading…
Reference in a new issue