@@ -6,9 +6,11 @@ package download
66import (
77 "bytes"
88 "context"
9+ "crypto/sha256"
910 "encoding/json"
1011 "errors"
1112 "fmt"
13+ "io"
1214 "net/http"
1315 "net/http/httptest"
1416 "os"
@@ -246,6 +248,11 @@ func (t *testFixture) oneShot(ctx context.Context, u Update) {
246248 t .etags ["test/bundle1" ] = u .ETag
247249}
248250
251+ type fileInfo struct {
252+ name string
253+ length int64
254+ }
255+
249256type testServer struct {
250257 t * testing.T
251258 customAuth func (http.ResponseWriter , * http.Request ) error
@@ -256,6 +263,7 @@ type testServer struct {
256263 server * httptest.Server
257264 etagInResponse bool
258265 longPoll bool
266+ testdataHashes map [string ]fileInfo
259267}
260268
261269func newTestServer (t * testing.T ) * testServer {
@@ -339,68 +347,58 @@ func (t *testServer) handle(w http.ResponseWriter, r *http.Request) {
339347
340348 var buf bytes.Buffer
341349
342- if r .URL .Path == "/v2/org/repo/manifests/latest" {
343- w .Header ().Add ("Content-Length" , "596" )
344- w .Header ().Add ("Content-Type" , "application/vnd.oci.image.manifest.v1+json" )
345- w .Header ().Add ("Docker-Content-Digest" , "sha256:fe9c2930b6d8cc1bf3fa0c560996a95c75f0d0668bee71138355d9784c8c99b8" )
346- w .WriteHeader (200 )
347- return
348- }
349- if r .URL .Path == "/v2/org/repo/manifests/sha256:fe9c2930b6d8cc1bf3fa0c560996a95c75f0d0668bee71138355d9784c8c99b8" {
350- w .Header ().Add ("Content-Length" , "596" )
351- w .Header ().Add ("Content-Type" , "application/vnd.oci.image.manifest.v1+json" )
352- w .Header ().Add ("Docker-Content-Digest" , "sha256:fe9c2930b6d8cc1bf3fa0c560996a95c75f0d0668bee71138355d9784c8c99b8" )
353- w .WriteHeader (200 )
354- bs , err := os .ReadFile ("testdata/manifest.layer" )
355- if err != nil {
356- w .WriteHeader (404 )
357- return
350+ if strings .HasPrefix (r .URL .Path , "/v2/org/repo/" ) {
351+ // build test data to hash map to serve testdata files by hash
352+ if t .testdataHashes == nil {
353+ t .testdataHashes = make (map [string ]fileInfo )
354+ files , err := os .ReadDir ("testdata" )
355+ if err != nil {
356+ t .t .Fatalf ("failed to read testdata directory: %s" , err )
357+ }
358+ for _ , file := range files {
359+ if file .IsDir () {
360+ continue
361+ }
362+ hash , length , err := getFileSHAandSize ("testdata/" + file .Name ())
363+ if err != nil {
364+ t .t .Fatalf ("failed to read testdata file: %s" , err )
365+ }
366+ t .testdataHashes [fmt .Sprintf ("%x" , hash )] = fileInfo {name : file .Name (), length : length }
367+ }
358368 }
359- buf .WriteString (string (bs ))
360- w .Write (buf .Bytes ())
361- return
362369 }
363- if r .URL .Path == "/v2/org/repo/blobs/sha256:c5834dbce332cabe6ae68a364de171a50bf5b08024c27d7c08cc72878b4df7ff" {
364- w .Header ().Add ("Content-Length" , "464" )
365- w .Header ().Add ("Content-Type" , "application/vnd.oci.image.layer.v1.tar+gzip,application/vnd.oci.image.config.v1+json" )
366- w .Header ().Add ("Docker-Content-Digest" , "sha256:c5834dbce332cabe6ae68a364de171a50bf5b08024c27d7c08cc72878b4df7ff" )
367- w .WriteHeader (200 )
368- bs , err := os .ReadFile ("testdata/manifest.layer" )
369- if err != nil {
370- w .WriteHeader (404 )
371- return
372- }
373- buf .WriteString (string (bs ))
374- buf .WriteTo (w )
375370
376- return
377- }
378- if r .URL .Path == "/v2/org/repo/blobs/sha256:b206ac766b0f3f880f6a62c4bb5ba5192d29deaefd989a1961603346a7555bdd" {
379- w .Header ().Add ("Content-Length" , "568" )
380- w .Header ().Add ("Content-Type" , "application/vnd.oci.image.layer.v1.tar+gzip" )
381- w .Header ().Add ("Docker-Content-Digest" , "sha256:b206ac766b0f3f880f6a62c4bb5ba5192d29deaefd989a1961603346a7555bdd" )
382- w .WriteHeader (200 )
383- bs , err := os .ReadFile ("testdata/tar.layer" )
384- if err != nil {
385- w .WriteHeader (404 )
371+ if strings .HasPrefix (r .URL .Path , "/v2/org/repo/blobs/sha256:" ) || strings .HasPrefix (r .URL .Path , "/v2/org/repo/manifests/sha256:" ) {
372+ sha := strings .TrimPrefix (strings .TrimPrefix (r .URL .Path , "/v2/org/repo/blobs/sha256:" ), "/v2/org/repo/manifests/sha256:" )
373+ if fileInfo , ok := t .testdataHashes [sha ]; ok {
374+ w .Header ().Add ("Content-Length" , strconv .Itoa (int (fileInfo .length )))
375+ w .Header ().Add ("Content-Type" , "application/gzip" )
376+ w .Header ().Add ("Docker-Content-Digest" , "sha256:" + sha )
377+ w .WriteHeader (200 )
378+ bs , err := os .ReadFile ("testdata/" + fileInfo .name )
379+ if err != nil {
380+ w .WriteHeader (404 )
381+ return
382+ }
383+ buf .WriteString (string (bs ))
384+ w .Write (buf .Bytes ())
386385 return
387386 }
388- buf .WriteString (string (bs ))
389- w .Write (buf .Bytes ())
387+ w .WriteHeader (404 )
390388 return
391389 }
392- if r .URL .Path == "/v2/org/repo/blobs/sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a" {
393- w .Header ().Add ("Content-Length" , "2" )
394- w .Header ().Add ("Content-Type" , "application/vnd.oci.image.config.v1+json" )
395- w .Header ().Add ("Docker-Content-Digest" , "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a" )
396- w .WriteHeader (200 )
397- bs , err := os .ReadFile ("testdata/config.layer" )
390+
391+ if strings .HasPrefix (r .URL .Path , "/v2/org/repo/manifests/" ) {
392+ sha , size , err := getFileSHAandSize ("testdata/" + strings .TrimPrefix (r .URL .Path , "/v2/org/repo/manifests/" ) + ".manifest" )
398393 if err != nil {
399394 w .WriteHeader (404 )
400395 return
401396 }
402- buf .WriteString (string (bs ))
403- w .Write (buf .Bytes ())
397+
398+ w .Header ().Add ("Content-Length" , strconv .Itoa (int (size )))
399+ w .Header ().Add ("Content-Type" , "application/vnd.oci.image.manifest.v1+json" )
400+ w .Header ().Add ("Docker-Content-Digest" , "sha256:" + fmt .Sprintf ("%x" , sha ))
401+ w .WriteHeader (200 )
404402 return
405403 }
406404 name := strings .TrimPrefix (r .URL .Path , "/bundles/" )
@@ -487,3 +485,17 @@ func getPreferHeaderField(r *http.Request, field string) string {
487485 }
488486 return ""
489487}
488+
489+ func getFileSHAandSize (filePath string ) ([]byte , int64 , error ) {
490+ f , err := os .Open (filePath )
491+ if err != nil {
492+ return nil , 0 , err
493+ }
494+ defer f .Close ()
495+ hash := sha256 .New ()
496+ w , err := io .Copy (hash , f )
497+ if err != nil {
498+ return nil , w , err
499+ }
500+ return hash .Sum (nil ), w , nil
501+ }
0 commit comments