Summary
Bundle.entry.request.ifNoneMatch is parsed into BundleEntry.if_none_match and read by nothing, so a conditional read in a bundle (GET Patient/1 with ifNoneMatch: W/"4", spec fixture entry 9) always answers 200 with the body instead of 304. Discussion #28's TransactionEntryRequest carries if_none_match by design.
Evidence
- Field:
crates/persistence/src/core/transaction.rs:266-268. Populated in parse_bundle_entry (crates/rest/src/handlers/batch.rs:2107-2122, function starts :2060).
- No reader: a repo-wide search for
.if_none_match in crates/rest and crates/persistence finds only the S3 client's unrelated HTTP header use and EntityTagPrecondition::if_none_match_satisfied (core/preconditions.rs:270), which nothing on the bundle path calls.
- The batch GET arm (
batch.rs:930-963) returns BundleEntryResult::ok(stored) unconditionally and never reads the field from the request; the transaction GET arms in the backends do the same.
crates/rest/README.md states it is "parsed and ignored".
Proposed fix
In both GET arms, evaluate ifNoneMatch with EntityTagPrecondition (already the shared parser for ifMatch) and answer 304 Not Modified with no body when satisfied, mirroring the resource endpoint's conditional read. Tests: batch and transaction GET with a matching and a stale tag, plus *.
Found while validating #511 (see PR #860).
Summary
Bundle.entry.request.ifNoneMatchis parsed intoBundleEntry.if_none_matchand read by nothing, so a conditional read in a bundle (GET Patient/1withifNoneMatch: W/"4", spec fixture entry 9) always answers 200 with the body instead of 304. Discussion #28'sTransactionEntryRequestcarriesif_none_matchby design.Evidence
crates/persistence/src/core/transaction.rs:266-268. Populated inparse_bundle_entry(crates/rest/src/handlers/batch.rs:2107-2122, function starts:2060)..if_none_matchincrates/restandcrates/persistencefinds only the S3 client's unrelated HTTP header use andEntityTagPrecondition::if_none_match_satisfied(core/preconditions.rs:270), which nothing on the bundle path calls.batch.rs:930-963) returnsBundleEntryResult::ok(stored)unconditionally and never reads the field from the request; the transaction GET arms in the backends do the same.crates/rest/README.mdstates it is "parsed and ignored".Proposed fix
In both GET arms, evaluate
ifNoneMatchwithEntityTagPrecondition(already the shared parser forifMatch) and answer304 Not Modifiedwith no body when satisfied, mirroring the resource endpoint's conditional read. Tests: batch and transaction GET with a matching and a stale tag, plus*.Found while validating #511 (see PR #860).