Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat: support to download file with basic auth #487

Merged
merged 1 commit into from
Dec 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions cmd/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ type downloadOption struct {
MaxAttempts int
AcceptPreRelease bool
RoundTripper http.RoundTripper
Username string
Password string
Magnet bool
Force bool
Mod int
Expand Down Expand Up @@ -143,6 +145,8 @@ func (o *downloadOption) addDownloadFlags(flags *pflag.FlagSet) {
flags.IntVarP(&o.Thread, "thread", "t", viper.GetInt("thread"),
`Download file with multi-threads. It only works when its value is bigger than 1`)
flags.BoolVarP(&o.NoProxy, "no-proxy", "", viper.GetBool("no-proxy"), "Indicate no HTTP proxy taken")
flags.StringVarP(&o.Username, "username", "u", "", "The username for the HTTP basic auth")
flags.StringVarP(&o.Password, "password", "p", "", "The password for the HTTP basic auth")
}

func (o *downloadOption) fetch() (err error) {
Expand Down Expand Up @@ -322,6 +326,7 @@ func (o *downloadOption) runE(cmd *cobra.Command, args []string) (err error) {
downloader.WithoutProxy(o.NoProxy).
WithRoundTripper(o.RoundTripper).
WithInsecureSkipVerify(o.SkipTLS).
WithBasicAuth(o.Username, o.Password).
WithTimeout(o.Timeout)
err = downloader.DownloadWithContinue(targetURL, o.Output, o.ContinueAt, -1, 0, o.ShowProgress)
} else {
Expand All @@ -332,6 +337,7 @@ func (o *downloadOption) runE(cmd *cobra.Command, args []string) (err error) {
WithoutProxy(o.NoProxy).
WithRoundTripper(o.RoundTripper).
WithInsecureSkipVerify(o.SkipTLS).
WithBasicAuth(o.Username, o.Password).
WithTimeout(o.Timeout)
err = downloader.Download(targetURL, o.Output, o.Thread)
}
Expand Down
25 changes: 22 additions & 3 deletions pkg/net/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ func DownloadFileWithMultipleThreadKeepParts(targetURL, targetFilePath string, t
type ContinueDownloader struct {
downloader *HTTPDownloader

UserName, Password string
Timeout time.Duration
Context context.Context
roundTripper http.RoundTripper
Expand Down Expand Up @@ -261,6 +262,13 @@ func (c *ContinueDownloader) WithTimeout(timeout time.Duration) *ContinueDownloa
return c
}

// WithBasicAuth sets the basic auth
func (c *ContinueDownloader) WithBasicAuth(username, password string) *ContinueDownloader {
c.UserName = username
c.Password = password
return c
}

// DownloadWithContinue downloads the files continuously
func (c *ContinueDownloader) DownloadWithContinue(targetURL, output string, index, continueAt, end int64, showProgress bool) (err error) {
c.downloader = &HTTPDownloader{
Expand All @@ -270,6 +278,8 @@ func (c *ContinueDownloader) DownloadWithContinue(targetURL, output string, inde
NoProxy: c.noProxy,
RoundTripper: c.roundTripper,
InsecureSkipVerify: c.insecureSkipVerify,
UserName: c.UserName,
Password: c.Password,
Context: c.Context,
Timeout: c.Timeout,
}
Expand All @@ -293,16 +303,18 @@ func (c *ContinueDownloader) DownloadWithContinue(targetURL, output string, inde
return
}

// DetectSizeWithRoundTripper returns the size of target resource
func DetectSizeWithRoundTripper(targetURL, output string, showProgress, noProxy, insecureSkipVerify bool,
roundTripper http.RoundTripper, timeout time.Duration) (total int64, rangeSupport bool, err error) {
// DetectSizeWithRoundTripperAndAuth returns the size of target resource
func DetectSizeWithRoundTripperAndAuth(targetURL, output string, showProgress, noProxy, insecureSkipVerify bool,
roundTripper http.RoundTripper, username, password string, timeout time.Duration) (total int64, rangeSupport bool, err error) {
downloader := HTTPDownloader{
TargetFilePath: output,
URL: targetURL,
ShowProgress: showProgress,
RoundTripper: roundTripper,
NoProxy: false, // below HTTP request does not need proxy
InsecureSkipVerify: insecureSkipVerify,
UserName: username,
Password: password,
Timeout: timeout,
}

Expand Down Expand Up @@ -331,6 +343,13 @@ func DetectSizeWithRoundTripper(targetURL, output string, showProgress, noProxy,
return
}

// DetectSizeWithRoundTripper returns the size of target resource
// Deprecated, use DetectSizeWithRoundTripperAndAuth instead
func DetectSizeWithRoundTripper(targetURL, output string, showProgress, noProxy, insecureSkipVerify bool,
roundTripper http.RoundTripper, timeout time.Duration) (total int64, rangeSupport bool, err error) {
return DetectSizeWithRoundTripperAndAuth(targetURL, output, showProgress, noProxy, insecureSkipVerify, roundTripper, "", "", timeout)
}

// ParseSuggestedFilename parse the filename from resp header,More details from https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
func ParseSuggestedFilename(header http.Header, filepath string) (filename string) {
if disposition, ok := header["Content-Disposition"]; ok && len(disposition) >= 1 {
Expand Down
20 changes: 15 additions & 5 deletions pkg/net/multi_thread.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@
keepParts, showProgress bool
insecureSkipVerify bool

roundTripper http.RoundTripper
suggestedFilename string
timeout time.Duration
username, password string
roundTripper http.RoundTripper
suggestedFilename string
timeout time.Duration
}

// GetSuggestedFilename returns the suggested filename
Expand Down Expand Up @@ -62,13 +63,20 @@
return d
}

// WithBasicAuth sets the basic auth
func (d *MultiThreadDownloader) WithBasicAuth(username, password string) *MultiThreadDownloader {
d.username = username
d.password = password
return d

Check warning on line 70 in pkg/net/multi_thread.go

View check run for this annotation

Codecov / codecov/patch

pkg/net/multi_thread.go#L67-L70

Added lines #L67 - L70 were not covered by tests
}

// Download starts to download the target URL
func (d *MultiThreadDownloader) Download(targetURL, targetFilePath string, thread int) (err error) {
// get the total size of the target file
var total int64
var rangeSupport bool
if total, rangeSupport, err = DetectSizeWithRoundTripper(targetURL, targetFilePath, d.showProgress,
d.noProxy, d.insecureSkipVerify, d.roundTripper, d.timeout); rangeSupport && err != nil {
if total, rangeSupport, err = DetectSizeWithRoundTripperAndAuth(targetURL, targetFilePath, d.showProgress,
d.noProxy, d.insecureSkipVerify, d.roundTripper, d.username, d.password, d.timeout); rangeSupport && err != nil {
return
}

Expand Down Expand Up @@ -120,6 +128,7 @@
downloader.WithoutProxy(d.noProxy).
WithRoundTripper(d.roundTripper).
WithInsecureSkipVerify(d.insecureSkipVerify).
WithBasicAuth(d.username, d.password).
WithContext(ctx).WithTimeout(d.timeout)
if downloadErr := downloader.DownloadWithContinue(targetURL, output,
int64(index), start, end, d.showProgress); downloadErr != nil {
Expand Down Expand Up @@ -173,6 +182,7 @@
downloader.WithRoundTripper(d.roundTripper)
downloader.WithInsecureSkipVerify(d.insecureSkipVerify)
downloader.WithTimeout(d.timeout)
downloader.WithBasicAuth(d.username, d.password)
err = downloader.DownloadWithContinue(targetURL, targetFilePath, -1, 0, 0, true)
d.suggestedFilename = downloader.GetSuggestedFilename()
}
Expand Down
Loading