Add ETag and If-None-Match support to GET /node/ledger-chunk/{chunk_name}#7653
Add ETag and If-None-Match support to GET /node/ledger-chunk/{chunk_name}#7653
Conversation
Closes #7652 - Compute sha-256 ETag over served content (respects Range header) - Support sha-256, sha-384, sha-512 algorithms in If-None-Match - Return 304 Not Modified when ETag matches - Widen Matcher regex to accept algorithm:digest format - Add ETAG and IF_NONE_MATCH header constants - Add unit tests for new ETag format - Update CHANGELOG and documentation Co-authored-by: achamayou <4016369+achamayou@users.noreply.github.com>
|
@copilot rebase on the latest main, and make any adjustments necessary please. |
- Resolve merge conflicts with Want-Repr-Digest (#7651) changes - Fix ETag check to handle both HTTP 200 OK (no Range) and 206 Partial Content (with Range) from fill_range_response_from_file() - Merge CHANGELOG, docs, and header constant additions Co-authored-by: achamayou <4016369+achamayou@users.noreply.github.com>
Merged latest main (including #7651 Want-Repr-Digest changes) and adapted the ETag code to handle both |
|
@copilot rebase on the latest main, and make any adjustments necessary please. |
|
@copilot extend the test called test_ledger_chunk_access in e2e_operations to:
|
Extends test_ledger_chunk_access in e2e_operations.py with: 1. Normal GET returns correctly formed ETag with sha-256:<hex> format 2. Non-matching If-None-Match returns 200 OK with full body 3. Matching If-None-Match returns 304 Not Modified 4. Same checks on a sub-Range of the file (206 / 304) Co-authored-by: achamayou <4016369+achamayou@users.noreply.github.com>
Branch is already up to date with latest main. The
Extended
|
|
@copilot update the Matcher logic to throw a dedicated exception, which subclasses std::exception, on validation error paths, rather than std::runtime_error. Updated all calling sites to catch and handle that exception. |
Add ccf::http::MatcherError (subclassing std::exception) for Matcher validation errors. Update all calling sites: - file_serving_handlers.h: catch MatcherError instead of runtime_error - logging.cpp: add try/catch at all 6 Matcher sites, return 400 Bad Request - http_etag_test.cpp: expect MatcherError in tests Co-authored-by: achamayou <4016369+achamayou@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR adds ETag and If-None-Match support to the GET /node/ledger-chunk/{chunk_name} endpoint, implementing the feature requested in issue #7652. The implementation follows RFC 9530 structured field format for ETags, using digest values in the form "sha-256=:<base64_digest>:". The ETag is computed over the actual response content (which may be a partial range), and clients can use If-None-Match with sha-256, sha-384, or sha-512 digests to avoid re-downloading unchanged content.
Changes:
- Extended the
Matcherclass inhttp_etag.hto support RFC 9530 digest format by widening the regex pattern and introducing a dedicatedMatcherErrorexception - Added ETag computation and If-None-Match handling to the ledger chunk download endpoint, with support for three digest algorithms
- Updated all existing
Matchercall sites to properly catch the newMatcherErrorexception - Added comprehensive e2e tests covering ETag functionality with both full and range requests
- Documented the new feature with usage examples and sequence diagrams
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| include/ccf/http_consts.h | Added ETAG and IF_NONE_MATCH header constants |
| include/ccf/http_etag.h | Introduced MatcherError exception class and widened regex to accept RFC 9530 format |
| src/http/test/http_etag_test.cpp | Updated exception types and added test cases for RFC 9530 digest ETags |
| samples/apps/logging/logging.cpp | Added MatcherError exception handling at all Matcher call sites |
| src/node/rpc/file_serving_handlers.h | Implemented ETag computation and If-None-Match validation with multi-algorithm support |
| tests/e2e_operations.py | Added comprehensive e2e tests for ETag/If-None-Match with full and range requests |
| doc/operations/ledger_snapshot.rst | Documented ETag/If-None-Match feature with examples and mermaid diagrams |
| CHANGELOG.md | Added changelog entry for the new feature |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Move ETag computation and If-None-Match handling from the get_ledger_chunk handler into fill_range_response_from_file() so that both GET and HEAD requests (including Range requests) receive ETag headers. This also gives snapshots ETag support for free. HEAD requests now go through the same Range and ETag logic as GET, but without setting a response body. Add e2e tests for HEAD with ETag and HEAD with If-None-Match. Co-authored-by: achamayou <4016369+achamayou@users.noreply.github.com>
…fy header access - Check body content matches exactly (not just length) for non-matching If-None-Match on both full and range requests - Add sha-512 If-None-Match test for completeness alongside sha-384 - Simplify etag header access to use lowercase "etag" consistently (CCF sends it as lowercase per HTTP/2 conventions) - Check partial body content on non-matching range If-None-Match Co-authored-by: achamayou <4016369+achamayou@users.noreply.github.com>
include/ccf/http_consts.h: AddETAGandIF_NONE_MATCHheader constantsinclude/ccf/http_etag.h: Widen Matcher regex to acceptalgorithm:digestETag format; add dedicatedMatcherErrorexceptionsrc/node/rpc/file_serving_handlers.h: Move ETag/If-None-Match logic intofill_range_response_from_file()for GET+HEAD supportsrc/http/test/http_etag_test.cpp: Add test cases for the new ETag format withalgorithm:digestvalues; useMatcherErrorsamples/apps/logging/logging.cpp: CatchMatcherErrorat all Matcher calling sitesCHANGELOG.md: Add changelog entry for ETag/If-None-Match supportdoc/operations/ledger_snapshot.rst: Document the new ETag/If-None-Match feature with mermaid diagramstest_ledger_chunk_accesse2e test with ETag/If-None-Match checks for GET and HEADCloses #7652
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.