MCPcopy Index your code
hub / github.com/cph6/zsync / GetControlFile

Function GetControlFile

control_file_fetch.go:29–109  ·  view source on GitHub ↗

GetControlFile reads a zsync control file using the provided HTTPRequester. If keepZsync is non-empty, the control file is also cached locally. The returned string is the referer URL that should be used when resolving any relative URLs contained in the control file. This is a helper function that is

(client HTTPRequester, source, keepZsync, referer string)

Source from the content-addressed store, hash-verified

27// with a different client. This is essentially just a HTTP downloader with
28// mtime/If-Modified-Since caching..
29func GetControlFile(client HTTPRequester, source, keepZsync, referer string) (io.ReadCloser, string, error) {
30 u, err := url.Parse(source)
31 if err != nil || u.Scheme == "" {
32 return nil, "", fmt.Errorf("%s is not a valid URL", source)
33 }
34
35 var fileInfo os.FileInfo
36 gotMtime := false
37 if keepZsync != "" {
38 fileInfo, err = os.Stat(keepZsync)
39 if err != nil && !os.IsNotExist(err) {
40 fmt.Fprintf(os.Stderr, "failed to get mtime for existing .zsync control file: %v", err)
41 // Fall through with no mtime - we can just download the control file.
42 } else if err == nil {
43 gotMtime = true
44 }
45 }
46
47 req, err := http.NewRequest("GET", source, nil)
48 if err != nil {
49 return nil, "", fmt.Errorf("failed to form HTTP request: %w", err)
50 }
51 if referer != "" {
52 req.Header.Set("Referer", referer)
53 }
54 if gotMtime {
55 req.Header.Set("If-Modified-Since", fileInfo.ModTime().UTC().Format(time.RFC1123))
56 }
57
58 resp, err := client.Do(req)
59 if err != nil {
60 return nil, "", fmt.Errorf("HTTP request failed: %w", err)
61 }
62 if keepZsync != "" && resp.StatusCode == http.StatusNotModified {
63 // Not modified, so we can drop the response and read the local copy.
64 fmt.Fprintf(os.Stderr, "control file not modified - using local copy\n")
65 _ = resp.Body.Close()
66 f, err := os.Open(keepZsync)
67 return f, source, err
68 }
69 // Otherwise we need the response.
70 if resp.StatusCode != http.StatusOK {
71 _ = resp.Body.Close()
72 return nil, "", fmt.Errorf("failed to download .zsync: %s", resp.Status)
73 }
74
75 // If we are not saving a local copy of the .zsync file, we can just
76 // pass the response body reader to the caller.
77 if keepZsync == "" {
78 return resp.Body, source, nil
79 }
80
81 controlFile, err := os.Create(keepZsync)
82 if err != nil {
83 return nil, "", fmt.Errorf("zsync local file creation failed: %w", err)
84 }
85 // Copy zsync file from response to temporary file, then seek back to the
86 // start for reading.

Callers 1

getZsyncControlFileFunction · 0.92

Calls 4

setMTimeFunction · 0.85
CloseMethod · 0.80
DoMethod · 0.65
SetMethod · 0.45

Tested by

no test coverage detected