in go/downloader/downloader.go [90:174]
func download(ctx context.Context, crlUrl url.URL, path string, timeout time.Duration) error {
client := &http.Client{Timeout: timeout}
action, offset, size := determineAction(client, crlUrl, path)
if action == UpToDate {
return nil
}
req, err := http.NewRequestWithContext(ctx, "GET", crlUrl.String(), nil)
if err != nil {
return err
}
req.Header.Add("X-Automated-Tool", "https://github.com/mozilla/crlite")
if action == Resume {
req.Header.Add("Content-Range", fmt.Sprintf("bytes: %d-%d/%d", offset, size, offset-size))
}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
var outFileParams int
switch resp.StatusCode {
case http.StatusPartialContent:
// Depending on what the server responds with, we may have to go back to Create
outFileParams = os.O_APPEND | os.O_WRONLY
action = Resume
glog.V(1).Infof("[%s] Successfully resumed download at offset %d", crlUrl.String(), offset)
case http.StatusOK:
outFileParams = os.O_TRUNC | os.O_CREATE | os.O_WRONLY
action = Create
default:
return fmt.Errorf("Non-OK status: %s", resp.Status)
}
outFile, err := os.OpenFile(path, outFileParams, 0644)
if err != nil {
return err
}
defer outFile.Close()
if ctx.Err() != nil {
return ctx.Err()
}
defer resp.Body.Close()
// and copy from reader, propagating errors
totalBytes, err := io.Copy(outFile, resp.Body)
if err != nil {
return err
}
if action == Create && size != 0 && totalBytes != size {
glog.Warningf("[%s] Didn't seem to download the right number of bytes, expected=%d got %d",
crlUrl.String(), size, totalBytes)
}
if action == Resume && size != 0 && totalBytes+offset != size {
glog.Warningf("[%s] Didn't seem to download the right number of bytes, expected=%d got %d with %d already local",
crlUrl.String(), size, totalBytes, offset)
}
lastModStr := resp.Header.Get("Last-Modified")
// http.TimeFormat is 29 characters
if len(lastModStr) < 16 {
glog.Infof("[%s] No compliant reported last-modified time, file may expire early: [%s]", crlUrl.String(), lastModStr)
return nil
}
lastMod, err := http.ParseTime(resp.Header.Get("Last-Modified"))
if err != nil {
glog.Warningf("[%s] Couldn't parse modified time: %s [%s]", crlUrl.String(), err, lastModStr)
return nil
}
if err := os.Chtimes(path, lastMod, lastMod); err != nil {
glog.Warningf("Couldn't set modified time: %s", err)
}
return nil
}