Treat a clean EOF with unknown total as the whole asset
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/build Pipeline was successful

This commit is contained in:
2026-10-10 01:10:07 +11:00
parent 09ab49ef42
commit fdbf322ca8
2 changed files with 30 additions and 8 deletions
+5 -2
View File
@@ -62,7 +62,7 @@ func AssetStatusError(url string, resp *http.Response) error {
// ReadPrefix reads up to n bytes of a 200 or 206 asset response. full reports
// that the body is the whole object (per Content-Length or the Content-Range
// total); a body ending before n bytes that is not the whole object is a
// total, or a clean EOF before n when the total is unknown); a body ending before n bytes that is not the whole object is a
// transient short read.
func ReadPrefix(resp *http.Response, n int64) (body []byte, full bool, err error) {
body, err = io.ReadAll(io.LimitReader(resp.Body, n))
@@ -70,15 +70,18 @@ func ReadPrefix(resp *http.Response, n int64) (body []byte, full bool, err error
return nil, false, err
}
total := resp.ContentLength
unknown := resp.StatusCode == http.StatusOK && total == -1
if resp.StatusCode == http.StatusPartialContent {
total = -1
if _, t, ok := strings.Cut(resp.Header.Get("Content-Range"), "/"); ok {
if v, perr := strconv.ParseInt(t, 10, 64); perr == nil {
total = v
}
unknown = t == "*"
}
}
full = total == int64(len(body))
// net/http errors on a premature close, so a clean EOF before n with an unknown total is the whole object.
full = total == int64(len(body)) || (unknown && int64(len(body)) < n)
if !full && int64(len(body)) < n {
return nil, false, fmt.Errorf("short read: got %d of %d bytes", len(body), n)
}