processResp runs the CheckApply work for an http response. It does everything that happens after the typical `!apply {}` stage, and after we've received an *http.Response. It's split out into a helper with this kind of type signature because we may process from a standalone CheckApply, or we may pro
(ctx context.Context, resp *http.Response, apply bool)
| 796 | // http request to get the data for CheckApply! This runs the Close on the body. |
| 797 | // This has the same return signature as what is used when running CheckApply... |
| 798 | func (obj *HTTPClientRes) processResp(ctx context.Context, resp *http.Response, apply bool) (bool, error) { |
| 799 | |
| 800 | defer resp.Body.Close() |
| 801 | if obj.init.Debug { |
| 802 | obj.init.Logf("resp: %v", resp) |
| 803 | } |
| 804 | |
| 805 | // Did the http server tell us that our file is already just fine? |
| 806 | if resp.StatusCode == http.StatusNotModified && obj.MtimeCheck { |
| 807 | obj.init.Logf("file is up to date, skipping download") |
| 808 | content, err := obj.readAll() |
| 809 | if err != nil { |
| 810 | return false, err |
| 811 | } |
| 812 | if err := obj.send(content); err != nil { // send/recv |
| 813 | return false, err |
| 814 | } |
| 815 | |
| 816 | // 304 means our on-disk data is still current. Record this as |
| 817 | // the outcome and let publishResponse decide what to do with |
| 818 | // the bridge. Usually it leaves the last captured value alone |
| 819 | // (so a steady stream of 304s never surfaces as a status), but |
| 820 | // it seeds a 200 on a fresh start where the bridge is empty. |
| 821 | obj.status = http.StatusNotModified |
| 822 | obj.output = obj.dst |
| 823 | return true, nil |
| 824 | } |
| 825 | if resp.StatusCode != http.StatusOK { |
| 826 | obj.status = resp.StatusCode // report the HTTP code (eg: 404, 500) |
| 827 | obj.output = "" |
| 828 | return false, fmt.Errorf("unexpected status: %s", resp.Status) |
| 829 | } |
| 830 | |
| 831 | // TODO: are there more ways to early return with (true, nil) right now? |
| 832 | |
| 833 | // In noop mode we must not write to disk. The server has content for us |
| 834 | // but saving it (writing the file) is a change we're not allowed to do. |
| 835 | if !apply { |
| 836 | // XXX: leave the obj.status / obj.output untouched rather than |
| 837 | // reporting a code for data we didn't actually capture? |
| 838 | // XXX: do we need to send/recv in noop mode? |
| 839 | return false, nil |
| 840 | } |
| 841 | |
| 842 | // If we're writing a file, we should stream it to a vardir and then |
| 843 | // swap it atomically so that (1) we don't buffer the entire file into |
| 844 | // memory and (2) so that we don't have a partial (corrupt) file if the |
| 845 | // http fails to complete or validate the hash correctly. Note that we |
| 846 | // *don't* store the file twice in the steady state, since the vardir |
| 847 | // version overwrites the final destination when things check out okay. |
| 848 | tmpdel := true |
| 849 | defer func() { |
| 850 | // once file moved away, we should not run remove! |
| 851 | if !tmpdel { |
| 852 | return |
| 853 | } |
| 854 | // cleanup the partial file if not moved... |
| 855 | if err := os.Remove(obj.tmp); err != nil { |