diff options
author | KN4CK3R <admin@oldschoolhack.me> | 2022-11-24 15:25:13 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-24 16:25:13 +0200 |
commit | fc7a2d5a959334f7195571a3e1db669ed7667a28 (patch) | |
tree | e03df232ebc29e508680686c396cfecb4eeb0902 /routers | |
parent | 26f941fbdac73844a93c902ce6d1144175ff23ed (diff) | |
download | gitea-fc7a2d5a959334f7195571a3e1db669ed7667a28.tar.gz gitea-fc7a2d5a959334f7195571a3e1db669ed7667a28.zip |
Add support for HEAD requests in Maven registry (#21834)
Related #18543
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Diffstat (limited to 'routers')
-rw-r--r-- | routers/api/packages/api.go | 1 | ||||
-rw-r--r-- | routers/api/packages/composer/composer.go | 5 | ||||
-rw-r--r-- | routers/api/packages/conan/conan.go | 5 | ||||
-rw-r--r-- | routers/api/packages/generic/generic.go | 5 | ||||
-rw-r--r-- | routers/api/packages/helm/helm.go | 5 | ||||
-rw-r--r-- | routers/api/packages/maven/api.go | 7 | ||||
-rw-r--r-- | routers/api/packages/maven/maven.go | 57 | ||||
-rw-r--r-- | routers/api/packages/npm/npm.go | 10 | ||||
-rw-r--r-- | routers/api/packages/nuget/nuget.go | 10 | ||||
-rw-r--r-- | routers/api/packages/pub/pub.go | 5 | ||||
-rw-r--r-- | routers/api/packages/pypi/pypi.go | 5 | ||||
-rw-r--r-- | routers/api/packages/rubygems/rubygems.go | 5 | ||||
-rw-r--r-- | routers/api/packages/vagrant/vagrant.go | 5 | ||||
-rw-r--r-- | routers/api/v1/repo/file.go | 6 | ||||
-rw-r--r-- | routers/common/repo.go | 11 | ||||
-rw-r--r-- | routers/web/repo/repo.go | 5 | ||||
-rw-r--r-- | routers/web/user/package.go | 5 |
17 files changed, 120 insertions, 32 deletions
diff --git a/routers/api/packages/api.go b/routers/api/packages/api.go index 11e7e5d6a6..0d8b9ce61e 100644 --- a/routers/api/packages/api.go +++ b/routers/api/packages/api.go @@ -181,6 +181,7 @@ func CommonRoutes(ctx gocontext.Context) *web.Route { r.Group("/maven", func() { r.Put("/*", reqPackageAccess(perm.AccessModeWrite), maven.UploadPackageFile) r.Get("/*", maven.DownloadPackageFile) + r.Head("/*", maven.ProvidePackageFileHeader) }, reqPackageAccess(perm.AccessModeRead)) r.Group("/nuget", func() { r.Group("", func() { // Needs to be unauthenticated for the NuGet client. diff --git a/routers/api/packages/composer/composer.go b/routers/api/packages/composer/composer.go index 92e83dbe79..a19433c6f0 100644 --- a/routers/api/packages/composer/composer.go +++ b/routers/api/packages/composer/composer.go @@ -184,7 +184,10 @@ func DownloadPackageFile(ctx *context.Context) { } defer s.Close() - ctx.ServeContent(pf.Name, s, pf.CreatedUnix.AsLocalTime()) + ctx.ServeContent(s, &context.ServeHeaderOptions{ + Filename: pf.Name, + LastModified: pf.CreatedUnix.AsLocalTime(), + }) } // UploadPackage creates a new package diff --git a/routers/api/packages/conan/conan.go b/routers/api/packages/conan/conan.go index 188cfce287..e7c891b35f 100644 --- a/routers/api/packages/conan/conan.go +++ b/routers/api/packages/conan/conan.go @@ -477,7 +477,10 @@ func downloadFile(ctx *context.Context, fileFilter container.Set[string], fileKe } defer s.Close() - ctx.ServeContent(pf.Name, s, pf.CreatedUnix.AsLocalTime()) + ctx.ServeContent(s, &context.ServeHeaderOptions{ + Filename: pf.Name, + LastModified: pf.CreatedUnix.AsLocalTime(), + }) } // DeleteRecipeV1 deletes the requested recipe(s) diff --git a/routers/api/packages/generic/generic.go b/routers/api/packages/generic/generic.go index 1bccc6764c..1c233da20f 100644 --- a/routers/api/packages/generic/generic.go +++ b/routers/api/packages/generic/generic.go @@ -53,7 +53,10 @@ func DownloadPackageFile(ctx *context.Context) { } defer s.Close() - ctx.ServeContent(pf.Name, s, pf.CreatedUnix.AsLocalTime()) + ctx.ServeContent(s, &context.ServeHeaderOptions{ + Filename: pf.Name, + LastModified: pf.CreatedUnix.AsLocalTime(), + }) } // UploadPackage uploads the specific generic package. diff --git a/routers/api/packages/helm/helm.go b/routers/api/packages/helm/helm.go index 17f0a0d311..11291ca14e 100644 --- a/routers/api/packages/helm/helm.go +++ b/routers/api/packages/helm/helm.go @@ -138,7 +138,10 @@ func DownloadPackageFile(ctx *context.Context) { } defer s.Close() - ctx.ServeContent(pf.Name, s, pf.CreatedUnix.AsLocalTime()) + ctx.ServeContent(s, &context.ServeHeaderOptions{ + Filename: pf.Name, + LastModified: pf.CreatedUnix.AsLocalTime(), + }) } // UploadPackage creates a new package diff --git a/routers/api/packages/maven/api.go b/routers/api/packages/maven/api.go index b60a317814..4ca541dd6f 100644 --- a/routers/api/packages/maven/api.go +++ b/routers/api/packages/maven/api.go @@ -6,7 +6,6 @@ package maven import ( "encoding/xml" - "sort" "strings" packages_model "code.gitea.io/gitea/models/packages" @@ -23,12 +22,8 @@ type MetadataResponse struct { Version []string `xml:"versioning>versions>version"` } +// pds is expected to be sorted ascending by CreatedUnix func createMetadataResponse(pds []*packages_model.PackageDescriptor) *MetadataResponse { - sort.Slice(pds, func(i, j int) bool { - // Maven and Gradle order packages by their creation timestamp and not by their version string - return pds[i].Version.CreatedUnix < pds[j].Version.CreatedUnix - }) - var release *packages_model.PackageDescriptor versions := make([]string, 0, len(pds)) diff --git a/routers/api/packages/maven/maven.go b/routers/api/packages/maven/maven.go index de274b2046..3125062b92 100644 --- a/routers/api/packages/maven/maven.go +++ b/routers/api/packages/maven/maven.go @@ -16,6 +16,8 @@ import ( "net/http" "path/filepath" "regexp" + "sort" + "strconv" "strings" packages_model "code.gitea.io/gitea/models/packages" @@ -34,6 +36,10 @@ const ( extensionSHA1 = ".sha1" extensionSHA256 = ".sha256" extensionSHA512 = ".sha512" + extensionPom = ".pom" + extensionJar = ".jar" + contentTypeJar = "application/java-archive" + contentTypeXML = "text/xml" ) var ( @@ -49,6 +55,15 @@ func apiError(ctx *context.Context, status int, obj interface{}) { // DownloadPackageFile serves the content of a package func DownloadPackageFile(ctx *context.Context) { + handlePackageFile(ctx, true) +} + +// ProvidePackageFileHeader provides only the headers describing a package +func ProvidePackageFileHeader(ctx *context.Context) { + handlePackageFile(ctx, false) +} + +func handlePackageFile(ctx *context.Context, serveContent bool) { params, err := extractPathParameters(ctx) if err != nil { apiError(ctx, http.StatusBadRequest, err) @@ -58,7 +73,7 @@ func DownloadPackageFile(ctx *context.Context) { if params.IsMeta && params.Version == "" { serveMavenMetadata(ctx, params) } else { - servePackageFile(ctx, params) + servePackageFile(ctx, params, serveContent) } } @@ -82,6 +97,11 @@ func serveMavenMetadata(ctx *context.Context, params parameters) { return } + sort.Slice(pds, func(i, j int) bool { + // Maven and Gradle order packages by their creation timestamp and not by their version string + return pds[i].Version.CreatedUnix < pds[j].Version.CreatedUnix + }) + xmlMetadata, err := xml.Marshal(createMetadataResponse(pds)) if err != nil { apiError(ctx, http.StatusInternalServerError, err) @@ -89,6 +109,9 @@ func serveMavenMetadata(ctx *context.Context, params parameters) { } xmlMetadataWithHeader := append([]byte(xml.Header), xmlMetadata...) + latest := pds[len(pds)-1] + ctx.Resp.Header().Set("Last-Modified", latest.Version.CreatedUnix.Format(http.TimeFormat)) + ext := strings.ToLower(filepath.Ext(params.Filename)) if isChecksumExtension(ext) { var hash []byte @@ -110,10 +133,15 @@ func serveMavenMetadata(ctx *context.Context, params parameters) { return } - ctx.PlainTextBytes(http.StatusOK, xmlMetadataWithHeader) + ctx.Resp.Header().Set("Content-Length", strconv.Itoa(len(xmlMetadataWithHeader))) + ctx.Resp.Header().Set("Content-Type", contentTypeXML) + + if _, err := ctx.Resp.Write(xmlMetadataWithHeader); err != nil { + log.Error("write bytes failed: %v", err) + } } -func servePackageFile(ctx *context.Context, params parameters) { +func servePackageFile(ctx *context.Context, params parameters, serveContent bool) { packageName := params.GroupID + "-" + params.ArtifactID pv, err := packages_model.GetVersionByNameAndVersion(ctx, ctx.Package.Owner.ID, packages_model.TypeMaven, packageName, params.Version) @@ -165,6 +193,23 @@ func servePackageFile(ctx *context.Context, params parameters) { return } + opts := &context.ServeHeaderOptions{ + ContentLength: &pb.Size, + LastModified: pf.CreatedUnix.AsLocalTime(), + } + switch ext { + case extensionJar: + opts.ContentType = contentTypeJar + case extensionPom: + opts.ContentType = contentTypeXML + } + + if !serveContent { + ctx.SetServeHeaders(opts) + ctx.Status(http.StatusOK) + return + } + s, err := packages_module.NewContentStore().Get(packages_module.BlobHash256Key(pb.HashSHA256)) if err != nil { apiError(ctx, http.StatusInternalServerError, err) @@ -177,7 +222,9 @@ func servePackageFile(ctx *context.Context, params parameters) { } } - ctx.ServeContent(pf.Name, s, pf.CreatedUnix.AsLocalTime()) + opts.Filename = pf.Name + + ctx.ServeContent(s, opts) } // UploadPackageFile adds a file to the package. If the package does not exist, it gets created. @@ -273,7 +320,7 @@ func UploadPackageFile(ctx *context.Context) { } // If it's the package pom file extract the metadata - if ext == ".pom" { + if ext == extensionPom { pfci.IsLead = true var err error diff --git a/routers/api/packages/npm/npm.go b/routers/api/packages/npm/npm.go index af0e9be56e..6c11286a86 100644 --- a/routers/api/packages/npm/npm.go +++ b/routers/api/packages/npm/npm.go @@ -103,7 +103,10 @@ func DownloadPackageFile(ctx *context.Context) { } defer s.Close() - ctx.ServeContent(pf.Name, s, pf.CreatedUnix.AsLocalTime()) + ctx.ServeContent(s, &context.ServeHeaderOptions{ + Filename: pf.Name, + LastModified: pf.CreatedUnix.AsLocalTime(), + }) } // DownloadPackageFileByName finds the version and serves the contents of a package @@ -146,7 +149,10 @@ func DownloadPackageFileByName(ctx *context.Context) { } defer s.Close() - ctx.ServeContent(pf.Name, s, pf.CreatedUnix.AsLocalTime()) + ctx.ServeContent(s, &context.ServeHeaderOptions{ + Filename: pf.Name, + LastModified: pf.CreatedUnix.AsLocalTime(), + }) } // UploadPackage creates a new package diff --git a/routers/api/packages/nuget/nuget.go b/routers/api/packages/nuget/nuget.go index 442d94243b..06aaca596d 100644 --- a/routers/api/packages/nuget/nuget.go +++ b/routers/api/packages/nuget/nuget.go @@ -342,7 +342,10 @@ func DownloadPackageFile(ctx *context.Context) { } defer s.Close() - ctx.ServeContent(pf.Name, s, pf.CreatedUnix.AsLocalTime()) + ctx.ServeContent(s, &context.ServeHeaderOptions{ + Filename: pf.Name, + LastModified: pf.CreatedUnix.AsLocalTime(), + }) } // UploadPackage creates a new package with the metadata contained in the uploaded nupgk file @@ -562,7 +565,10 @@ func DownloadSymbolFile(ctx *context.Context) { } defer s.Close() - ctx.ServeContent(pf.Name, s, pf.CreatedUnix.AsLocalTime()) + ctx.ServeContent(s, &context.ServeHeaderOptions{ + Filename: pf.Name, + LastModified: pf.CreatedUnix.AsLocalTime(), + }) } // DeletePackage hard deletes the package diff --git a/routers/api/packages/pub/pub.go b/routers/api/packages/pub/pub.go index 635147b6d0..26cb9fbb9a 100644 --- a/routers/api/packages/pub/pub.go +++ b/routers/api/packages/pub/pub.go @@ -275,5 +275,8 @@ func DownloadPackageFile(ctx *context.Context) { } defer s.Close() - ctx.ServeContent(pf.Name, s, pf.CreatedUnix.AsLocalTime()) + ctx.ServeContent(s, &context.ServeHeaderOptions{ + Filename: pf.Name, + LastModified: pf.CreatedUnix.AsLocalTime(), + }) } diff --git a/routers/api/packages/pypi/pypi.go b/routers/api/packages/pypi/pypi.go index 4853e6658b..76801a92e1 100644 --- a/routers/api/packages/pypi/pypi.go +++ b/routers/api/packages/pypi/pypi.go @@ -95,7 +95,10 @@ func DownloadPackageFile(ctx *context.Context) { } defer s.Close() - ctx.ServeContent(pf.Name, s, pf.CreatedUnix.AsLocalTime()) + ctx.ServeContent(s, &context.ServeHeaderOptions{ + Filename: pf.Name, + LastModified: pf.CreatedUnix.AsLocalTime(), + }) } // UploadPackageFile adds a file to the package. If the package does not exist, it gets created. diff --git a/routers/api/packages/rubygems/rubygems.go b/routers/api/packages/rubygems/rubygems.go index 4adfb15731..f0b00f42c3 100644 --- a/routers/api/packages/rubygems/rubygems.go +++ b/routers/api/packages/rubygems/rubygems.go @@ -192,7 +192,10 @@ func DownloadPackageFile(ctx *context.Context) { } defer s.Close() - ctx.ServeContent(pf.Name, s, pf.CreatedUnix.AsLocalTime()) + ctx.ServeContent(s, &context.ServeHeaderOptions{ + Filename: pf.Name, + LastModified: pf.CreatedUnix.AsLocalTime(), + }) } // UploadPackageFile adds a file to the package. If the package does not exist, it gets created. diff --git a/routers/api/packages/vagrant/vagrant.go b/routers/api/packages/vagrant/vagrant.go index 31ac56a532..746a2b19ba 100644 --- a/routers/api/packages/vagrant/vagrant.go +++ b/routers/api/packages/vagrant/vagrant.go @@ -239,5 +239,8 @@ func DownloadPackageFile(ctx *context.Context) { } defer s.Close() - ctx.ServeContent(pf.Name, s, pf.CreatedUnix.AsLocalTime()) + ctx.ServeContent(s, &context.ServeHeaderOptions{ + Filename: pf.Name, + LastModified: pf.CreatedUnix.AsLocalTime(), + }) } diff --git a/routers/api/v1/repo/file.go b/routers/api/v1/repo/file.go index 6dead81e6d..aba5b1f9e7 100644 --- a/routers/api/v1/repo/file.go +++ b/routers/api/v1/repo/file.go @@ -341,7 +341,11 @@ func download(ctx *context.APIContext, archiveName string, archiver *repo_model. return } defer fr.Close() - ctx.ServeContent(downloadName, fr, archiver.CreatedUnix.AsLocalTime()) + + ctx.ServeContent(fr, &context.ServeHeaderOptions{ + Filename: downloadName, + LastModified: archiver.CreatedUnix.AsLocalTime(), + }) } // GetEditorconfig get editor config of a repository diff --git a/routers/common/repo.go b/routers/common/repo.go index f4b813d6b4..340eb1809f 100644 --- a/routers/common/repo.go +++ b/routers/common/repo.go @@ -5,7 +5,6 @@ package common import ( - "fmt" "io" "path" "path/filepath" @@ -52,16 +51,16 @@ func ServeData(ctx *context.Context, filePath string, size int64, reader io.Read buf = buf[:n] } + opts := &context.ServeHeaderOptions{ + Filename: path.Base(filePath), + } + if size >= 0 { - ctx.Resp.Header().Set("Content-Length", fmt.Sprintf("%d", size)) + opts.ContentLength = &size } else { log.Error("ServeData called to serve data: %s with size < 0: %d", filePath, size) } - opts := &context.ServeHeaderOptions{ - Filename: path.Base(filePath), - } - sniffedType := typesniffer.DetectContentType(buf) isPlain := sniffedType.IsText() || ctx.FormBool("render") diff --git a/routers/web/repo/repo.go b/routers/web/repo/repo.go index 7bcca1d02a..17e600182d 100644 --- a/routers/web/repo/repo.go +++ b/routers/web/repo/repo.go @@ -426,7 +426,10 @@ func download(ctx *context.Context, archiveName string, archiver *repo_model.Rep } defer fr.Close() - ctx.ServeContent(downloadName, fr, archiver.CreatedUnix.AsLocalTime()) + ctx.ServeContent(fr, &context.ServeHeaderOptions{ + Filename: downloadName, + LastModified: archiver.CreatedUnix.AsLocalTime(), + }) } // InitiateDownload will enqueue an archival request, as needed. It may submit diff --git a/routers/web/user/package.go b/routers/web/user/package.go index 7179e2df97..7be37b6a50 100644 --- a/routers/web/user/package.go +++ b/routers/web/user/package.go @@ -402,5 +402,8 @@ func DownloadPackageFile(ctx *context.Context) { } defer s.Close() - ctx.ServeContent(pf.Name, s, pf.CreatedUnix.AsLocalTime()) + ctx.ServeContent(s, &context.ServeHeaderOptions{ + Filename: pf.Name, + LastModified: pf.CreatedUnix.AsLocalTime(), + }) } |