Skip to content

Commit 0112ab5

Browse files
committed
fix: use curl for windows runtime downloads
1 parent 8e7315c commit 0112ab5

2 files changed

Lines changed: 84 additions & 0 deletions

File tree

apps/WindowsLauncher/internal/launcher/artifact.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,20 @@ import (
99
"net/http"
1010
"net/url"
1111
"os"
12+
"os/exec"
1213
"path/filepath"
14+
"runtime"
1315
"strings"
1416

1517
"github.com/klauspost/compress/zstd"
1618
)
1719

1820
const defaultDownloadUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36 LoRAPilotInstaller/1.0"
1921

22+
var currentGOOS = runtime.GOOS
23+
var execLookPath = exec.LookPath
24+
var execCommandContext = exec.CommandContext
25+
2026
func DownloadFile(ctx context.Context, client *http.Client, sourceURL, destination string) error {
2127
if sourceURL == "" {
2228
return fmt.Errorf("download url is empty")
@@ -32,6 +38,12 @@ func DownloadFile(ctx context.Context, client *http.Client, sourceURL, destinati
3238
return copyFile(localPath, destination)
3339
}
3440

41+
if shouldUseCurlDownloader(sourceURL) {
42+
if err := downloadWithCurl(ctx, sourceURL, destination); err == nil {
43+
return nil
44+
}
45+
}
46+
3547
req, err := http.NewRequestWithContext(ctx, http.MethodGet, sourceURL, nil)
3648
if err != nil {
3749
return fmt.Errorf("build download request: %w", err)
@@ -61,6 +73,55 @@ func DownloadFile(ctx context.Context, client *http.Client, sourceURL, destinati
6173
return nil
6274
}
6375

76+
func shouldUseCurlDownloader(sourceURL string) bool {
77+
if currentGOOS != "windows" {
78+
return false
79+
}
80+
parsed, err := url.Parse(sourceURL)
81+
if err != nil {
82+
return false
83+
}
84+
if parsed.Scheme != "http" && parsed.Scheme != "https" {
85+
return false
86+
}
87+
_, err = execLookPath("curl.exe")
88+
return err == nil
89+
}
90+
91+
func buildCurlDownloadArgs(sourceURL, destination string) []string {
92+
return []string{
93+
"--silent",
94+
"--show-error",
95+
"--fail",
96+
"--location",
97+
"--retry",
98+
"5",
99+
"--retry-delay",
100+
"2",
101+
"--retry-all-errors",
102+
"--user-agent",
103+
defaultDownloadUserAgent,
104+
"--header",
105+
"Accept: */*",
106+
"--output",
107+
destination,
108+
sourceURL,
109+
}
110+
}
111+
112+
func downloadWithCurl(ctx context.Context, sourceURL, destination string) error {
113+
cmd := execCommandContext(ctx, "curl.exe", buildCurlDownloadArgs(sourceURL, destination)...)
114+
output, err := cmd.CombinedOutput()
115+
if err != nil {
116+
message := strings.TrimSpace(string(output))
117+
if message == "" {
118+
message = err.Error()
119+
}
120+
return fmt.Errorf("curl download %s: %s", sourceURL, message)
121+
}
122+
return nil
123+
}
124+
64125
func VerifySHA256File(path, want string) error {
65126
hashValue, err := SHA256File(path)
66127
if err != nil {

apps/WindowsLauncher/internal/launcher/launcher_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,29 @@ func TestDownloadFileSetsBrowserLikeHeaders(t *testing.T) {
145145
}
146146
}
147147

148+
func TestBuildCurlDownloadArgs(t *testing.T) {
149+
t.Parallel()
150+
151+
args := buildCurlDownloadArgs("https://cdn.example.com/rootfs.tar.zst", `C:\Temp\rootfs.tar.zst`)
152+
joined := strings.Join(args, "\n")
153+
for _, needle := range []string{
154+
"--fail",
155+
"--location",
156+
"--retry",
157+
"--retry-all-errors",
158+
"--user-agent",
159+
defaultDownloadUserAgent,
160+
"--header",
161+
"Accept: */*",
162+
`C:\Temp\rootfs.tar.zst`,
163+
"https://cdn.example.com/rootfs.tar.zst",
164+
} {
165+
if !strings.Contains(joined, needle) {
166+
t.Fatalf("missing curl argument %q in %q", needle, joined)
167+
}
168+
}
169+
}
170+
148171
func TestToWSLPath(t *testing.T) {
149172
t.Parallel()
150173

0 commit comments

Comments
 (0)