Skip to content

feat(backend): add configurable range compliance check for HTTP backend#1881

Open
yxxhero wants to merge 4 commits into
mainfrom
feat/range-compliance-check
Open

feat(backend): add configurable range compliance check for HTTP backend#1881
yxxhero wants to merge 4 commits into
mainfrom
feat/range-compliance-check

Conversation

@yxxhero

@yxxhero yxxhero commented Jun 17, 2026

Copy link
Copy Markdown
Member

Description

Add enableRangeComplianceCheck config option (default: false) to the dfdaemon backend configuration. When enabled, the HTTP backend validates that origin servers honor Range requests for non-zero-offset pieces by checking for 206 Partial Content status and matching Content-Range header.

This prevents silent data corruption when registry mirrors or other origins ignore Range headers and return the full body with 200 OK — causing reader.take(piece_length) to write the blob's leading bytes at the wrong offset.

Motivation

When downloading from registry mirrors (e.g. Harbor, Nexus) that proxy requests to upstream registries, some origins ignore the Range header and return the full blob with 200 OK. Dragonfly splits downloads into pieces and uses reader.take(piece_length) to read each piece. For non-zero-offset pieces, this silently reads the blob's leading bytes and writes them at the wrong offset, corrupting the reassembled file with a mismatched sha256.

This feature adds an opt-in validation to detect and reject such responses.

Changes

  • dragonfly-client-config/src/dfdaemon.rs: Add enable_range_compliance_check field to Backend struct with default value false
  • dragonfly-client-backend/src/http.rs: Add enable_range_compliance_check to HTTP struct and constructor; extract validation logic into validate_range_response() method
  • dragonfly-client-backend/src/lib.rs: Pass config.backend.enable_range_compliance_check to HTTP::new()

Configuration

backend:
  enableRangeComplianceCheck: true  # opt-in to range compliance validation

Test Coverage

  • should_get_partial_content_for_nonzero_range — 206 with matching Content-Range succeeds
  • should_reject_when_origin_ignores_range_and_returns_200 — 200 for non-zero offset is rejected
  • should_reject_when_content_range_start_mismatches — 206 with wrong Content-Range start is rejected
  • should_allow_full_body_for_zero_offset_range — 200 for zero-offset (first piece) is allowed

Signed-off-by: yxxhero aiopsclub@163.com

Add enableRangeComplianceCheck config option (default: true) to the
dfdaemon backend configuration. When enabled, the HTTP backend validates
that origin servers honor Range requests for non-zero-offset pieces by
checking for 206 Partial Content status and matching Content-Range header.

This prevents silent data corruption when registry mirrors or other
origins ignore Range headers and return the full body with 200 OK.

The validation logic is extracted into a dedicated validate_range_response
method for readability, consistent with existing helper methods in the
HTTP backend implementation.

Signed-off-by: yxxhero <aiopsclub@163.com>
@yxxhero yxxhero requested review from a team as code owners June 17, 2026 03:51
@yxxhero yxxhero added the enhancement New feature or request label Jun 17, 2026
yxxhero added 2 commits June 17, 2026 11:54
Signed-off-by: yxxhero <aiopsclub@163.com>
@codecov

codecov Bot commented Jun 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.61165% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 46.75%. Comparing base (e8d1657) to head (9bcafec).
⚠️ Report is 23 commits behind head on main.

Files with missing lines Patch % Lines
dragonfly-client-backend/src/http.rs 99.60% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1881      +/-   ##
==========================================
+ Coverage   45.98%   46.75%   +0.76%     
==========================================
  Files          93       93              
  Lines       23437    23778     +341     
==========================================
+ Hits        10778    11117     +339     
- Misses      12659    12661       +2     
Files with missing lines Coverage Δ
dragonfly-client-backend/src/lib.rs 92.40% <100.00%> (+0.06%) ⬆️
dragonfly-client-config/src/dfdaemon.rs 90.16% <100.00%> (+0.04%) ⬆️
dragonfly-client-backend/src/http.rs 96.49% <99.60%> (+1.30%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Signed-off-by: yxxhero <aiopsclub@163.com>
@pmady

pmady commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

this is a solid safety net — without it a broken origin that ignores Range headers would silently serve the full file starting from byte 0, and pieces would get corrupted without any error. seen this happen with CDNs that strip Range on cache misses.

the check being opt-in via enable_range_compliance_check is the right call since some origins legitimately return 200 for the first piece (start=0). and the Content-Range start offset validation catches the edge case where you get a 206 back but for the wrong byte range.

one thought — when start_matches is None (no Content-Range header at all on a 206), should that be treated as an error or a pass? right now it fails because unwrap_or(false). some origins return 206 without Content-Range which is technically a protocol violation but its common enough in the wild. might want to log a warning instead of hard-failing in that case, or at least make that behavior configurable too

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants