Add a minimal JSON template to the PyPI registry

This commit is contained in:
Zachary Spector 2026-04-12 12:23:00 +12:00 committed by clayote
parent fd28fd896b
commit 6e63fe3b01
3 changed files with 46 additions and 0 deletions

View file

@ -581,6 +581,7 @@ func CommonRoutes() *web.Route {
r.Post("/", reqPackageAccess(perm.AccessModeWrite), enforcePackagesQuota(), pypi.UploadPackageFile)
r.Get("/files/{id}/{version}/{filename}", pypi.DownloadPackageFile)
r.Get("/simple/{id}", pypi.PackageMetadata)
r.Get("/{id}/json", pypi.JSONPackageMetadata)
}, reqPackageAccess(perm.AccessModeRead))
r.Group("/rpm", func() {
r.Group("/repository.key", func() {

View file

@ -75,6 +75,37 @@ func PackageMetadata(ctx *context.Context) {
ctx.HTML(http.StatusOK, "api/packages/pypi/simple")
}
// JSONPackageMetadata returns the same data as PackageMetadata, but in JSON
func JSONPackageMetadata(ctx *contex.Context) {
packageName := normalizer.Replace(ctx.Params("id"))
pvs, err := packages_model.GetVersionsByPackageName(ctx, ctx.Package.Owner.ID, packages_model.TypePyPI, packageName)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
if len(pvs) == 0 {
apiError(ctx, http.StatusNotFound, err)
return
}
pds, err := packages_model.GetPackageDescriptors(ctx, pvs)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
// sort package descriptors by version to mimic PyPI format
sort.Slice(pds, func(i, j int) bool {
return strings.Compare(pds[i].Version.Version, pds[j].Version.Version) < 0
})
ctx.Data["RegistryURL"] = setting.AppURL + "api/packages/" + ctx.Package.Owner.Name + "/pypi"
ctx.Data["PackageDescriptor"] = pds[0]
ctx.Data["PackageDescriptors"] = pds
ctx.JSONTemplate(http.StatusOK, "api/packages/pypi/simple")
}
// DownloadPackageFile serves the content of a package
func DownloadPackageFile(ctx *context.Context) {
packageName := normalizer.Replace(ctx.Params("id"))

View file

@ -0,0 +1,14 @@
{
"info": {
"name": "{{.PackageDescriptor.Package.Name}}",
"urls": [{{range .PackageDescriptors}}{{$p := ..}}{{range .Files}}
{
"digests": {
"sha256": "{{.Blob.HashSHA256}}"
},
"url": "{{$.RegistryURL}}/files/{{$p.Package.LowerName}}/{{$p.Version.Version}}/{{.File.Name}}"{{if $p.Metadata.RequiresPython}},
"requires_python": "{{$p.Metadata.RequiresPython}}"{{end}}
}
{{end}}{{end}}]
}
}