@@ -2,97 +2,66 @@ package download
22
33import (
44 "context"
5- "crypto/sha256"
65 "encoding/hex"
76 "fmt"
87 "io"
8+ "mime"
99 "net/http"
1010 "net/url"
1111 "os"
1212 "path/filepath"
13- "time"
1413
14+ "github.com/cavaliergopher/grab/v3"
1515 "github.com/crc-org/crc/v2/pkg/crc/logging"
1616 "github.com/crc-org/crc/v2/pkg/crc/network/httpproxy"
1717 "github.com/crc-org/crc/v2/pkg/crc/version"
18- "github.com/crc-org/crc/v2/pkg/os/terminal"
19-
20- "github.com/cavaliergopher/grab/v3"
21- "github.com/cheggaaa/pb/v3"
2218 "github.com/pkg/errors"
2319)
2420
25- func doRequest (client * grab.Client , req * grab.Request ) (string , error ) {
26- const minSizeForProgressBar = 100_000_000
27-
28- resp := client .Do (req )
29- if resp .Size () < minSizeForProgressBar {
30- <- resp .Done
31- return resp .Filename , resp .Err ()
32- }
33-
34- t := time .NewTicker (500 * time .Millisecond )
35- defer t .Stop ()
36- var bar * pb.ProgressBar
37- if terminal .IsShowTerminalOutput () {
38- bar = pb .Start64 (resp .Size ())
39- bar .Set (pb .Bytes , true )
40- // This is the same as the 'Default' template https://github.com/cheggaaa/pb/blob/224e0746e1e7b9c5309d6e2637264bfeb746d043/v3/preset.go#L8-L10
41- // except that the 'per second' suffix is changed to '/s' (by default it is ' p/s' which is unexpected)
42- progressBarTemplate := `{{with string . "prefix"}}{{.}} {{end}}{{counters . }} {{bar . }} {{percent . }} {{speed . "%s/s" "??/s"}}{{with string . "suffix"}} {{.}}{{end}}`
43- bar .SetTemplateString (progressBarTemplate )
44- defer bar .Finish ()
45- }
46-
47- loop:
48- for {
49- select {
50- case <- t .C :
51- if terminal .IsShowTerminalOutput () {
52- bar .SetCurrent (resp .BytesComplete ())
53- }
54- case <- resp .Done :
55- break loop
56- }
57- }
58-
59- return resp .Filename , resp .Err ()
60- }
61-
6221// Download function takes sha256sum as hex decoded byte
6322// something like hex.DecodeString("33daf4c03f86120fdfdc66bddf6bfff4661c7ca11c5d")
64- func Download (ctx context.Context , uri , destination string , mode os.FileMode , sha256sum []byte ) (string , error ) {
23+ func Download (ctx context.Context , uri , destination string , mode os.FileMode , _ []byte ) (io. Reader , string , error ) {
6524 logging .Debugf ("Downloading %s to %s" , uri , destination )
6625
67- client := grab .NewClient ()
68- client .UserAgent = version .UserAgent ()
69- client .HTTPClient = & http.Client {Transport : httpproxy .HTTPTransport ()}
70- req , err := grab .NewRequest (destination , uri )
26+ req , err := http .NewRequestWithContext (ctx , "GET" , uri , nil )
27+
7128 if err != nil {
72- return "" , errors .Wrapf (err , "unable to get request from %s" , uri )
29+ return nil , "" , errors .Wrapf (err , "unable to get request from %s" , uri )
7330 }
31+ client := http.Client {Transport : & http.Transport {}}
7432
7533 if ctx == nil {
7634 panic ("ctx is nil, this should not happen" )
7735 }
7836 req = req .WithContext (ctx )
7937
80- if sha256sum != nil {
81- req .SetChecksum (sha256 .New (), sha256sum , true )
38+ resp , err := client .Do (req )
39+ if err != nil {
40+ return nil , "" , err
8241 }
8342
84- filename , err := doRequest (client , req )
43+ var filename , dir string
44+ if filepath .Ext (destination ) == "crcbundle" {
45+ dir = filepath .Dir (destination )
46+ } else {
47+ dir = destination
48+ }
49+ if disposition , params , _ := mime .ParseMediaType (resp .Header .Get ("Content-Disposition" )); disposition == "attachment" {
50+ filename = filepath .Join (dir , params ["filename" ])
51+ } else {
52+ filename = filepath .Join (dir , filepath .Base (resp .Request .URL .Path ))
53+ }
54+ file , err := os .OpenFile (filename , os .O_CREATE | os .O_WRONLY | os .O_TRUNC , mode )
8555 if err != nil {
86- return "" , err
56+ return nil , "" , err
8757 }
8858
8959 if err := os .Chmod (filename , mode ); err != nil {
9060 _ = os .Remove (filename )
91- return "" , err
61+ return nil , "" , err
9262 }
9363
94- logging .Debugf ("Download saved to %v" , filename )
95- return filename , nil
64+ return io .TeeReader (resp .Body , file ), filename , nil
9665}
9766
9867// InMemory takes a URL and returns a ReadCloser object to the downloaded file
@@ -138,10 +107,10 @@ func NewRemoteFile(uri, sha256sum string) *RemoteFile {
138107
139108}
140109
141- func (r * RemoteFile ) Download (ctx context.Context , bundlePath string , mode os.FileMode ) (string , error ) {
110+ func (r * RemoteFile ) Download (ctx context.Context , bundlePath string , mode os.FileMode ) (io. Reader , string , error ) {
142111 sha256bytes , err := hex .DecodeString (r .sha256sum )
143112 if err != nil {
144- return "" , err
113+ return nil , "" , err
145114 }
146115 return Download (ctx , r .URI , bundlePath , mode , sha256bytes )
147116}
0 commit comments