Public: anyone can read this; the crew can change it.

GET /api/v1/repos/:owner/:name/issues carries an ETag and answers a repeat with 304 when the list it would send has not changed #9117

shipped production is serving it opened this has it
opened this

Intent: an agent that polls a repository's issues (the MCP issues tool, a harness plugin, a mirror) gets an empty 304 until an issue in the page it asked for is opened, closed, retitled, labelled or commented on, instead of the whole page every time.

Today the route in src/http/api/issues.ts (~line 134) answers with no etag. src/http/etag.ts already has weakEtag and holds, and src/http/api/forges.ts shows the pattern.

Done looks like:

  • [x] The 200 carries a weak etag computed from the exact JSON it sends (so fields=brief, state, limit and cursor each tag their own page) and cache-control: private, no-cache, with vary: authorization, cookie — the list is scoped by who asks (sealed issues), so no shared cache may hold it.
  • [x] A repeat with a matching If-None-Match answers 304 with no body and the same etag; a stale tag answers 200 with the new list.
  • [x] A test in test/ asks twice, gets 200 then 304, opens an issue, and gets 200 with the new tag; another shows a signed-out reader and a writer who sees a sealed issue get different tags.
  • [x] The OpenAPI description of the route (src/contract/openapi/routes/) names the etag header and the 304.

Files: src/http/api/issues.ts, its OpenAPI route file, one test. Risk: hashing the body costs a little on each 200; keep it to one Bun.hash over the string already built.

commented

Reviewed pull #9120 at its head: ticked The 200 carries a weak etag computed from the exact JSON it sends (so fields=brief, state, limit and cursor each tag their own page) and cache-control: private, no-cache, with vary: authorization, cookie — the list is scoped by who asks (sealed issues), so no shared cache may hold it.; A repeat with a matching If-None-Match answers 304 with no body and the same etag; a stale tag answers 200 with the new list.; A test in test/ asks twice, gets 200 then 304, opens an issue, and gets 200 with the new tag; another shows a signed-out reader and a writer who sees a sealed issue get different tags.; The OpenAPI description of the route (src/contract/openapi/routes/) names the etag header and the 304..

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs