refactor: npm route handlers (#39275)

This commit is contained in:
wxiaoguang
2026-09-08 23:15:40 +08:00
committed by GitHub
parent 8b6ad49a5f
commit 45a78bbc8e
4 changed files with 54 additions and 42 deletions
+14 -24
View File
@@ -9,6 +9,7 @@ import (
auth_model "gitea.dev/models/auth"
"gitea.dev/models/perm"
"gitea.dev/modules/log"
npm_module "gitea.dev/modules/packages/npm"
"gitea.dev/modules/setting"
"gitea.dev/modules/web"
"gitea.dev/routers/api/packages/alpine"
@@ -404,9 +405,13 @@ func CommonRoutes() *web.Router {
}, reqPackageAccess(perm.AccessModeRead))
})
r.Group("/npm", func() {
r.Group("/@{scope}/{id}", func() {
// HINT: NPM-ROUTE-PATH-PATTERN: search this keyword to see more details
scopeRegexp := `^@` + npm_module.RegexpNamePart + `$`
idRegexp := `^(@` + npm_module.RegexpNamePart + `%2[fF])?` + npm_module.RegexpNamePart + `$`
addPackageHandlers := func() {
r.Get("", npm.PackageMetadata)
r.Put("", reqPackageAccess(perm.AccessModeWrite), npm.UploadPackage)
r.Get("/{version}", npm.PackageVersionMetadata)
r.Group("/-/{version}/{filename}", func() {
r.Get("", npm.DownloadPackageFile)
r.Delete("/-rev/{revision}", reqPackageAccess(perm.AccessModeWrite), npm.DeletePackageVersion)
@@ -416,34 +421,19 @@ func CommonRoutes() *web.Router {
r.Delete("", npm.DeletePackage)
r.Put("", npm.DeletePreview)
}, reqPackageAccess(perm.AccessModeWrite))
})
r.Group("/{id}", func() {
r.Get("", npm.PackageMetadata)
r.Put("", reqPackageAccess(perm.AccessModeWrite), npm.UploadPackage)
r.Group("/-/{version}/{filename}", func() {
r.Get("", npm.DownloadPackageFile)
r.Delete("/-rev/{revision}", reqPackageAccess(perm.AccessModeWrite), npm.DeletePackageVersion)
})
r.Get("/-/{filename}", npm.DownloadPackageFileByName)
r.Group("/-rev/{revision}", func() {
r.Delete("", npm.DeletePackage)
r.Put("", npm.DeletePreview)
}, reqPackageAccess(perm.AccessModeWrite))
})
r.Group("/-/package/@{scope}/{id}/dist-tags", func() {
}
r.Group("/{scope:"+scopeRegexp+"}/{id:"+idRegexp+"}", addPackageHandlers)
r.Group("/{id:"+idRegexp+"}", addPackageHandlers)
addPackageDistTagsHandlers := func() {
r.Get("", npm.ListPackageTags)
r.Group("/{tag}", func() {
r.Put("", npm.AddPackageTag)
r.Delete("", npm.DeletePackageTag)
}, reqPackageAccess(perm.AccessModeWrite))
})
r.Group("/-/package/{id}/dist-tags", func() {
r.Get("", npm.ListPackageTags)
r.Group("/{tag}", func() {
r.Put("", npm.AddPackageTag)
r.Delete("", npm.DeletePackageTag)
}, reqPackageAccess(perm.AccessModeWrite))
})
}
r.Group("/-/package/{scope:"+scopeRegexp+"}/{id:"+idRegexp+"}/dist-tags", addPackageDistTagsHandlers)
r.Group("/-/package/{id:"+idRegexp+"}/dist-tags", addPackageDistTagsHandlers)
r.Group("/-/v1/search", func() {
r.Get("", npm.PackageSearch)
})
+16 -4
View File
@@ -41,14 +41,22 @@ func apiError(ctx *context.Context, status int, obj any) {
}
// packageNameFromParams gets the package name from the url parameters
// Variations: /name/, /@scope/name/, /@scope%2Fname/
func packageNameFromParams(ctx *context.Context) string {
// Real examples: these 2 both should work:
// * "https://registry.npmjs.org/@angular/core"
// * "https://registry.npmjs.org/@angular%2Fcore"
//
// HINT: NPM-ROUTE-PATH-PATTERN: The cases for the path parameters:
// * ".../TheName/...": id="TheName"
// * ".../@TheScope/TheName/...": scope="@TheScope", id="TheName"
// * ".../@TheScope%2FTheName/...": id="@TheScope/TheName"
scope := ctx.PathParam("scope")
id := ctx.PathParam("id")
fullOrSub := ctx.PathParam("id") // may be a full name or a subpath of the full package name
if scope != "" {
return fmt.Sprintf("@%s/%s", scope, id)
// now id is the subpath of the full package name, e.g. "core" in "@angular/core"
return fmt.Sprintf("%s/%s", scope, fullOrSub)
}
return id
return fullOrSub // id is the full package name, e.g.: "@angular/core" or "lodash"
}
// PackageMetadata returns the metadata for a single package
@@ -79,6 +87,10 @@ func PackageMetadata(ctx *context.Context) {
ctx.JSON(http.StatusOK, resp)
}
func PackageVersionMetadata(ctx *context.Context) {
ctx.HTTPError(http.StatusNotImplemented, "not implemented")
}
// DownloadPackageFile serves the content of a package
func DownloadPackageFile(ctx *context.Context) {
packageName := packageNameFromParams(ctx)