@@ -16,6 +16,8 @@ import (
1616 "net/http"
1717 "path/filepath"
1818 "regexp"
19+ "sort"
20+ "strconv"
1921 "strings"
2022
2123 packages_model "code.gitea.io/gitea/models/packages"
@@ -34,6 +36,10 @@ const (
3436 extensionSHA1 = ".sha1"
3537 extensionSHA256 = ".sha256"
3638 extensionSHA512 = ".sha512"
39+ extensionPom = ".pom"
40+ extensionJar = ".jar"
41+ contentTypeJar = "application/java-archive"
42+ contentTypeXML = "text/xml"
3743)
3844
3945var (
@@ -49,6 +55,15 @@ func apiError(ctx *context.Context, status int, obj interface{}) {
4955
5056// DownloadPackageFile serves the content of a package
5157func DownloadPackageFile (ctx * context.Context ) {
58+ handlePackageFile (ctx , true )
59+ }
60+
61+ // ProvidePackageFileHeader provides only the headers describing a package
62+ func ProvidePackageFileHeader (ctx * context.Context ) {
63+ handlePackageFile (ctx , false )
64+ }
65+
66+ func handlePackageFile (ctx * context.Context , serveContent bool ) {
5267 params , err := extractPathParameters (ctx )
5368 if err != nil {
5469 apiError (ctx , http .StatusBadRequest , err )
@@ -58,7 +73,7 @@ func DownloadPackageFile(ctx *context.Context) {
5873 if params .IsMeta && params .Version == "" {
5974 serveMavenMetadata (ctx , params )
6075 } else {
61- servePackageFile (ctx , params )
76+ servePackageFile (ctx , params , serveContent )
6277 }
6378}
6479
@@ -82,13 +97,21 @@ func serveMavenMetadata(ctx *context.Context, params parameters) {
8297 return
8398 }
8499
100+ sort .Slice (pds , func (i , j int ) bool {
101+ // Maven and Gradle order packages by their creation timestamp and not by their version string
102+ return pds [i ].Version .CreatedUnix < pds [j ].Version .CreatedUnix
103+ })
104+
85105 xmlMetadata , err := xml .Marshal (createMetadataResponse (pds ))
86106 if err != nil {
87107 apiError (ctx , http .StatusInternalServerError , err )
88108 return
89109 }
90110 xmlMetadataWithHeader := append ([]byte (xml .Header ), xmlMetadata ... )
91111
112+ latest := pds [len (pds )- 1 ]
113+ ctx .Resp .Header ().Set ("Last-Modified" , latest .Version .CreatedUnix .Format (http .TimeFormat ))
114+
92115 ext := strings .ToLower (filepath .Ext (params .Filename ))
93116 if isChecksumExtension (ext ) {
94117 var hash []byte
@@ -110,10 +133,15 @@ func serveMavenMetadata(ctx *context.Context, params parameters) {
110133 return
111134 }
112135
113- ctx .PlainTextBytes (http .StatusOK , xmlMetadataWithHeader )
136+ ctx .Resp .Header ().Set ("Content-Length" , strconv .Itoa (len (xmlMetadataWithHeader )))
137+ ctx .Resp .Header ().Set ("Content-Type" , contentTypeXML )
138+
139+ if _ , err := ctx .Resp .Write (xmlMetadataWithHeader ); err != nil {
140+ log .Error ("write bytes failed: %v" , err )
141+ }
114142}
115143
116- func servePackageFile (ctx * context.Context , params parameters ) {
144+ func servePackageFile (ctx * context.Context , params parameters , serveContent bool ) {
117145 packageName := params .GroupID + "-" + params .ArtifactID
118146
119147 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) {
165193 return
166194 }
167195
196+ opts := & context.ServeHeaderOptions {
197+ ContentLength : & pb .Size ,
198+ LastModified : pf .CreatedUnix .AsLocalTime (),
199+ }
200+ switch ext {
201+ case extensionJar :
202+ opts .ContentType = contentTypeJar
203+ case extensionPom :
204+ opts .ContentType = contentTypeXML
205+ }
206+
207+ if ! serveContent {
208+ ctx .SetServeHeaders (opts )
209+ ctx .Status (http .StatusOK )
210+ return
211+ }
212+
168213 s , err := packages_module .NewContentStore ().Get (packages_module .BlobHash256Key (pb .HashSHA256 ))
169214 if err != nil {
170215 apiError (ctx , http .StatusInternalServerError , err )
@@ -177,7 +222,9 @@ func servePackageFile(ctx *context.Context, params parameters) {
177222 }
178223 }
179224
180- ctx .ServeContent (pf .Name , s , pf .CreatedUnix .AsLocalTime ())
225+ opts .Filename = pf .Name
226+
227+ ctx .ServeContent (s , opts )
181228}
182229
183230// 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) {
273320 }
274321
275322 // If it's the package pom file extract the metadata
276- if ext == ".pom" {
323+ if ext == extensionPom {
277324 pfci .IsLead = true
278325
279326 var err error
0 commit comments