Why
/r/<name>/raw/<ref>/<path> streams the whole blob and does not implement byte
ranges: it sets Content-Length and copies, with no Accept-Ranges and no
handling of Range. A client resuming a download, or a player asking for a
few KiB, gets the whole file every time.
Measured in #100 with the load harness, an 8 MiB blob and Range: bytes=0-65535:
| route | requested | status | served | p50 |
|---|---|---|---|---|
/raw |
64 KiB | 200 | 8 MiB | 15 ms |
/releases/<tag>/artifacts/<name> |
1 KiB | 206 | 1 KiB | 4 ms |
The artifact route already answers ranges because it uses http.ServeContent
over a file. /raw streams from git cat-file, which cannot seek.
Scope
- Answer a single
Range: bytes=a-b(anda-,-n) with206,Content-Range, and only the requested bytes. AdvertiseAccept-Ranges: byteson the response. - A request without
Rangestays exactly as it is:200,Content-Length, the whole blob. - An unsatisfiable range (
apast the end) is416withContent-Range: bytes */<size>. - Multiple ranges may be answered with the whole file (
200); it is allowed and keeps the reader simple. - Reading a range still costs the bytes before it in the git stream; skipping is a copy into a discard buffer, not a seek. The win is what crosses the network, and it should be said in the code comment.
Acceptance
curl -r 0-1023on a raw file returns206,Content-Range: bytes 0-1023/<size>,Accept-Ranges: bytes, and 1024 bytes.- The no-range response is byte-for-byte what it is now.
- Tests cover a prefix range, a suffix range, an unsatisfiable range, and a file smaller than the range.
- The load harness
raw-rangescenario shows206and a body the size of the range.
Part of #100. The measurement and the comparison with the artifact route are recorded there.