Skip to content

Commit 7a46b41

Browse files
committed
feat(resume download): implement range header check
Signed-off-by: Saarthak Verma <saarthakverma739@gmail.com>
1 parent fe8472c commit 7a46b41

File tree

1 file changed

+28
-16
lines changed

1 file changed

+28
-16
lines changed

pkg/downloader/uri.go

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,16 @@ func calculateHashForPartialFile(file *os.File) (hash.Hash, error) {
215215
return hash, nil
216216
}
217217

218+
func (uri URI) checkSeverSupportsRangeHeader() (bool, error) {
219+
url := uri.ResolveURL()
220+
resp, err := http.Head(url)
221+
if err != nil {
222+
return false, err
223+
}
224+
defer resp.Body.Close()
225+
return resp.Header.Get("Accept-Ranges") == "bytes", nil
226+
}
227+
218228
func (uri URI) DownloadFile(filePath, sha string, fileN, total int, downloadStatus func(string, string, string, float64)) error {
219229
url := uri.ResolveURL()
220230
if uri.LooksLikeOCI() {
@@ -282,21 +292,23 @@ func (uri URI) DownloadFile(filePath, sha string, fileN, total int, downloadStat
282292
return fmt.Errorf("failed to create request for %q: %v", filePath, err)
283293
}
284294

285-
/* TODO
286-
* 1. ~~Mock downloads~~
287-
* 2. Check if server supports partial downloads
288-
* 3. ~~Resume partial downloads~~
289-
* 4. Ensure progressWriter accurately reflects progress if a partial file is present
290-
* 5. MAYBE:
291-
* a. Delete file if calculatedSHA != sha
292-
*/
293-
294295
// save partial download to dedicated file
295296
tmpFilePath := filePath + ".partial"
296297
tmpFileInfo, err := os.Stat(tmpFilePath)
297298
if err == nil {
298-
startPos := tmpFileInfo.Size()
299-
req.Header.Set("Range", fmt.Sprintf("bytes=%d-", startPos))
299+
support, err := uri.checkSeverSupportsRangeHeader()
300+
if err != nil {
301+
return fmt.Errorf("failed to check if uri server supports range header: %v", err)
302+
}
303+
if support {
304+
startPos := tmpFileInfo.Size()
305+
req.Header.Set("Range", fmt.Sprintf("bytes=%d-", startPos))
306+
} else {
307+
err := removePartialFile(tmpFilePath)
308+
if err != nil {
309+
return err
310+
}
311+
}
300312
} else if !errors.Is(err, os.ErrNotExist) {
301313
return fmt.Errorf("failed to check file %q existence: %v", filePath, err)
302314
}
@@ -341,6 +353,11 @@ func (uri URI) DownloadFile(filePath, sha string, fileN, total int, downloadStat
341353
return fmt.Errorf("failed to write file %q: %v", filePath, err)
342354
}
343355

356+
err = os.Rename(tmpFilePath, filePath)
357+
if err != nil {
358+
return fmt.Errorf("failed to rename temporary file %s -> %s: %v", tmpFilePath, filePath, err)
359+
}
360+
344361
if sha != "" {
345362
// Verify SHA
346363
calculatedSHA := fmt.Sprintf("%x", progress.hash.Sum(nil))
@@ -352,11 +369,6 @@ func (uri URI) DownloadFile(filePath, sha string, fileN, total int, downloadStat
352369
log.Debug().Msgf("SHA missing for %q. Skipping validation", filePath)
353370
}
354371

355-
err = os.Rename(tmpFilePath, filePath)
356-
if err != nil {
357-
return fmt.Errorf("failed to rename temporary file %s -> %s: %v", tmpFilePath, filePath, err)
358-
}
359-
360372
log.Info().Msgf("File %q downloaded and verified", filePath)
361373
if utils.IsArchive(filePath) {
362374
basePath := filepath.Dir(filePath)

0 commit comments

Comments
 (0)