1
0
Fork 0
forked from NYANDEV/forgejo

Allow for resolution of NPM registry paths that match upstream () ()

Backport ()

This PR fixes issue  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:
Wayne Starr 2022-11-09 00:00:09 -06:00 committed by GitHub
parent 14342047ad
commit 995ae06a6e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 1 deletions
integrations
routers/api/packages

View file

@ -123,10 +123,16 @@ func TestPackageNpm(t *testing.T) {
b, _ := base64.StdEncoding.DecodeString(data)
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)
assert.NoError(t, err)
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) {

View file

@ -199,11 +199,13 @@ func Routes() *web.Route {
r.Get("", npm.PackageMetadata)
r.Put("", reqPackageAccess(perm.AccessModeWrite), npm.UploadPackage)
r.Get("/-/{version}/{filename}", npm.DownloadPackageFile)
r.Get("/-/{filename}", npm.DownloadPackageFileByName)
})
r.Group("/{id}", func() {
r.Get("", npm.PackageMetadata)
r.Put("", reqPackageAccess(perm.AccessModeWrite), npm.UploadPackage)
r.Get("/-/{version}/{filename}", npm.DownloadPackageFile)
r.Get("/-/{filename}", npm.DownloadPackageFileByName)
})
r.Group("/-/package/@{scope}/{id}/dist-tags", func() {
r.Get("", npm.ListPackageTags)

View file

@ -105,6 +105,49 @@ func DownloadPackageFile(ctx *context.Context) {
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
func UploadPackage(ctx *context.Context) {
npmPackage, err := npm_module.ParsePackage(ctx.Req.Body)