Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

A free and open-source forge that lives in your Git repo.

#122

Answer byte ranges on raw downloads

merged · by keenan 10d ago · merged into main at 26c9be33 by keenan 10d ago

keenan opened this 10d ago

Why

Closes #119. /r/<name>/raw/<ref>/<path> streamed the whole blob and ignored Range, so a client resuming a download or asking for a few KiB got the whole file. Measured with the load harness in #100: a 64 KiB range of an 8 MiB blob returned 200 and 8 MiB, while the artifact route answered 206 because it uses http.ServeContent.

What changed

  • A single Range is answered with 206, Content-Range: bytes a-b/size, and only the requested bytes. Prefix (0-9), open-ended (15-) and suffix (-5) forms work, and an end past the file is clamped.
  • A range starting past the end is 416 with Content-Range: bytes */<size>.
  • Multiple ranges, an unknown unit, and a malformed header get the whole file with 200, which RFC 9110 allows. A client that asks for something the server does not implement gets a correct full response, not a broken one.
  • The no-range response keeps its bytes and gains Accept-Ranges: bytes.
  • HEAD now stops after the headers instead of reading the blob.

A blob is streamed from git cat-file, which cannot seek: a range is served by reading and discarding the bytes before it and copying only the requested part. The win is what does not cross the network (64 KiB instead of 8 MiB); the server still reads the skipped bytes. That is stated in the code.

Measurement

The harness’s raw-range scenario (64 KiB of an 8 MiB file, concurrency 4, 5 s):

status req/s p50 p90 p99
before (#100) 200 (8 MiB) 265.6 15 ms 17 ms 21 ms
after 206 (64 KiB) 365.6 11 ms 13 ms 17 ms

Checks

  • TestParseByteRange: every form, clamping, 416, and the headers that mean “whole file”.
  • TestRawAnswersByteRanges: the route end to end over a pushed file — no range, prefix, middle, open-ended, clamped end, suffix, suffix larger than the file, past-the-end 416, and the ignored headers.
  • gofmt, go vet ./..., python3 scripts/check-links.py, and the full -race suite with GOFLAGS=-tags=sqlite_fts5.
  • The load harness raw-range scenario reports 206, as #119 asked.

Discussion (0)

No discussion yet.