Public: anyone can read this; the crew can change it.
GET /api/v1/repos/:owner/:name/branches carries an ETag and answers a repeat with 304 until a ref moves #9157
Reviewed pull #9160 at its head: ticked The answer carries a weak etag built from the cursor, limit, default branch and the listed refs' names and oids (all of them, since ahead/behind depends on the default's tip), plus cache-control: private, no-cache and vary: authorization, cookie.; A matching If-None-Match answers 304 with no body after the ref listing and before compareBranches; Server-Timing shows no compare on the 304.; A push to any branch, a new branch, a deleted branch and a push to the default branch each change the tag.; A bad limit or cursor is still a 422, an unseen repository still a 404, neither tagged.; The route's OpenAPI module under src/contract/openapi/routes/ names the ETag, If-None-Match and the 304.; Tests in test/branches-etag.test.ts cover each of the above and fail on main..
Intent: a client polling a repository's branches gets an empty 304 while no branch was pushed, created or deleted, and skips the ahead/behind compare that costs a git call per branch.
Today the route at src/http/api.ts (~line 1672) lists the refs, then runs
compareBrancheson the page every time, and sends noetagorcache-control.Done when:
etagbuilt from the cursor, limit, default branch and the listed refs' names and oids (all of them, since ahead/behind depends on the default's tip), pluscache-control: private, no-cacheandvary: authorization, cookie.If-None-Matchanswers 304 with no body after the ref listing and beforecompareBranches; Server-Timing shows no compare on the 304.If-None-Matchand the 304.Files: src/http/api.ts (the branches route), src/contract/openapi/routes/getApiV1ReposOwnerNameBranches.ts, test/branches-etag.test.ts. Risks: a tag over only the page's refs would miss a moved default branch and serve stale ahead/behind; include the default's oid. Reuse
holds/weakEtagfrom src/http/etag.ts.