@@ -33,7 +33,7 @@ func TestSwiftPackageReleasesRewritesRegistryURLs(t *testing.T) {
3333
3434 proxy , _ , _ , _ := setupTestProxy (t )
3535 handler := NewSwiftHandler (proxy , "https://proxy.example" , upstream .URL + "/registry" ).Routes ()
36- req := httptest .NewRequest (http .MethodGet , "/apple/swift-argument-parser " , nil )
36+ req := httptest .NewRequest (http .MethodGet , "/APPLE/SWIFT-ARGUMENT-PARSER " , nil )
3737 req .Header .Set ("Accept" , swiftAcceptJSON )
3838 w := httptest .NewRecorder ()
3939 handler .ServeHTTP (w , req )
@@ -83,7 +83,7 @@ func TestSwiftReleaseMetadataSupportsJSONExtensionAndHead(t *testing.T) {
8383 handler := NewSwiftHandler (proxy , "https://proxy.example" , upstream .URL + "/registry" ).Routes ()
8484
8585 for _ , method := range []string {http .MethodGet , http .MethodHead } {
86- req := httptest .NewRequest (method , "/apple/example /1.2.3.json" , nil )
86+ req := httptest .NewRequest (method , "/APPLE/EXAMPLE /1.2.3.json" , nil )
8787 w := httptest .NewRecorder ()
8888 handler .ServeHTTP (w , req )
8989 if w .Code != http .StatusOK {
@@ -121,7 +121,7 @@ func TestSwiftManifestProxiesQueryAndRewritesLinks(t *testing.T) {
121121
122122 proxy , _ , _ , _ := setupTestProxy (t )
123123 handler := NewSwiftHandler (proxy , "https://proxy.example" , upstream .URL + "/registry" ).Routes ()
124- req := httptest .NewRequest (http .MethodGet , "/apple/example /1.2.3/Package.swift?swift-version=5.9" , nil )
124+ req := httptest .NewRequest (http .MethodGet , "/APPLE/EXAMPLE /1.2.3/Package.swift?swift-version=5.9" , nil )
125125 req .Header .Set ("Accept" , swiftAcceptManifest )
126126 w := httptest .NewRecorder ()
127127 handler .ServeHTTP (w , req )
@@ -271,6 +271,65 @@ func TestSwiftSourceArchiveRejectsChecksumMismatch(t *testing.T) {
271271 }
272272}
273273
274+ func TestSwiftSourceArchiveCanonicalizesPackageIdentity (t * testing.T ) {
275+ archive := []byte ("swift source archive" )
276+ checksumBytes := sha256 .Sum256 (archive )
277+ checksum := hex .EncodeToString (checksumBytes [:])
278+ var metadataPaths []string
279+
280+ upstream := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
281+ metadataPaths = append (metadataPaths , r .URL .Path )
282+ w .Header ().Set ("Content-Type" , "application/json" )
283+ _ , _ = fmt .Fprintf (w , `{"id":"apple.example","version":"1.2.3","resources":[{"name":"source-archive","type":"application/zip","checksum":%q}]}` , checksum )
284+ }))
285+ defer upstream .Close ()
286+
287+ proxy , db , store , fetcher := setupTestProxy (t )
288+ handler := NewSwiftHandler (proxy , "https://proxy.example" , upstream .URL ).Routes ()
289+ requestArchive := func (path string ) {
290+ fetcher .artifact = & fetch.Artifact {
291+ Body : io .NopCloser (strings .NewReader (string (archive ))),
292+ Size : int64 (len (archive )),
293+ ContentType : "application/zip" ,
294+ }
295+ w := httptest .NewRecorder ()
296+ handler .ServeHTTP (w , httptest .NewRequest (http .MethodGet , path , nil ))
297+ if w .Code != http .StatusOK {
298+ t .Fatalf ("GET %s status = %d, want 200; body: %s" , path , w .Code , w .Body .String ())
299+ }
300+ }
301+
302+ requestArchive ("/apple/example/1.2.3.zip" )
303+ requestArchive ("/APPLE/EXAMPLE/1.2.3.zip" )
304+
305+ if len (store .files ) != 1 {
306+ t .Errorf ("cached files = %d, want 1" , len (store .files ))
307+ }
308+ for _ , path := range metadataPaths {
309+ if path != "/apple/example/1.2.3" {
310+ t .Errorf ("metadata path = %q, want canonical lowercase path" , path )
311+ }
312+ }
313+
314+ canonicalPURL := packageurl .MakeString ("swift" , "apple/example" , "" )
315+ canonical , err := db .GetPackageByPURL (canonicalPURL )
316+ if err != nil {
317+ t .Fatalf ("getting canonical package: %v" , err )
318+ }
319+ if canonical == nil {
320+ t .Fatalf ("canonical package %q not found" , canonicalPURL )
321+ }
322+
323+ nonCanonicalPURL := packageurl .MakeString ("swift" , "APPLE/EXAMPLE" , "" )
324+ nonCanonical , err := db .GetPackageByPURL (nonCanonicalPURL )
325+ if err != nil {
326+ t .Fatalf ("getting non-canonical package: %v" , err )
327+ }
328+ if nonCanonical != nil {
329+ t .Errorf ("non-canonical package %q was cached" , nonCanonicalPURL )
330+ }
331+ }
332+
274333func TestSwiftSourceArchiveHeadRejectsCachedChecksumMismatch (t * testing.T ) {
275334 archive := []byte ("cached archive" )
276335 expectedChecksum := sha256 .Sum256 ([]byte ("expected archive" ))
0 commit comments