You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Fix Get Blob suffix range bytes=-1 500 on 1-byte blobs - #2862
Get Blob with a suffix range on a 1-byte block blob returned HTTP 500 instead of 206.
Range: bytes=-1 was parsed as start NaN, so Azurite logged NormalizedDownloadRange=bytes=NaN-0 and then threw a RangeError. Azure Storage returns 206 with the last byte (Content-Range: bytes 0-0/1).
Parse HTTP suffix-byte-range-spec (bytes=-N with N > 0) in deserializeRangeHeader, opt-in for downloads only (allowSuffixRange defaults to false).
Resolve suffix ranges against blob length in block, append, and page blob download before clamping.
Page mutations (Clear Pages and Upload Pages) reject suffix/empty ranges with HTTP 416. Get Page Ranges does not: suffix and empty values (bytes=-1, bytes=-99, bytes=-0, bytes=-, bytes=, empty) keep the upstream 200 (empty PageList). Malformed values such as bytes=5-2 and garbage still return 416 rather than 500.
bytes=-N (N > 0) on a 0-byte blob returns 416 with Content-Range: bytes */0 on both the block/append download path and the page blob download path.
Invalid suffix/empty Range on page-blob Get Blob (bytes=-0, bytes=-, bytes=) is ignored like block and append blobs (HTTP 200, full body) instead of 500.
Added an Upcoming Release entry in ChangeLog.md as required by this project's contribution guidelines.
Test helper: RangePolicyFactory sets only the Range header. InjectorPolicyFactory has its own policy that sets x-ms-range after SDK serialization, so existing Range-header tests still exercise the plain Range header.
Testing
Added coverage in tests/blob/apis/blob.test.ts and tests/blob/apis/pageblob.test.ts.
1-byte suffix download (unmodified upstream):
BlobAPIs
1) download suffix range bytes=-1 on a 1-byte blob @loki @sql
0 passing (84ms)
1 failing
1) BlobAPIs
download suffix range bytes=-1 on a 1-byte blob @loki @sql:
RestError
at handleErrorResponse (node_modules/@azure/core-client/src/deserializationPolicy.ts:255:17)
at deserializeResponseBody (node_modules/@azure/core-client/src/deserializationPolicy.ts:159:43)
at processTicksAndRejections (node:internal/process/task_queues:105:5)
After the download suffix fix (nearby download/range tests):
BlobAPIs
✔ download all parameters set @loki @sql
✔ download entire with range @loki @sql
✔ download out of range @loki @sql
✔ download invalid range @loki @sql
✔ download partial range (via custom policy) @loki @sql
✔ download suffix range bytes=-1 on a 1-byte blob @loki @sql
6 passing (122ms)
0-byte suffix download and page-mutation suffix ranges (on 43914f2):
0 passing (122ms)
4 failing
(0-byte downloads returned 206; populated clearPages returned 500; empty-map clearPages succeeded)
After opt-in suffix parsing and 0-byte 416:
4 passing (109ms)
Get Page Ranges and page-blob invalid Range (on d111d92, before this commit):
PageBlobAPIs
1) download ignores invalid suffix and empty Range like block blobs @loki
2) getPageRanges returns 200 for suffix or empty x-ms-range and 416 for malformed @loki
0 passing (75ms)
2 failing
1) RestError (page-blob Get Blob 500 for bytes=-0 / bytes=- / bytes=)
2) RestError: The page range specified is invalid.
(Get Page Ranges 416 for bytes=-1; upstream is 200)
After restoring Get Page Ranges 200 and ignoring invalid page-blob download ranges:
PageBlobAPIs
✔ download ignores invalid suffix and empty Range like block blobs @loki
✔ download suffix range bytes=-1 on a 0-byte page blob returns 416 @loki
✔ clearPages with suffix range bytes=-512 on a populated page map returns 416 @loki
✔ clearPages with suffix range bytes=-512 on an empty page map returns 416 @loki
✔ getPageRanges returns 200 for suffix or empty x-ms-range and 416 for malformed @loki
BlobAPIs
✔ download suffix range bytes=-1 on a 1-byte blob @loki @sql
✔ download suffix range bytes=-1 on a 0-byte blob returns 416 @loki @sql
7 passing (153ms)
loki suites (blob, pageblob, appendblob, blockblob, container, conditions) plus lint and tsc:
Suffix ranges bytes=-N are opt-in for blob downloads so page mutations
keep rejecting them. Zero-byte suffix downloads now return 416 with
Content-Range bytes */0.
Reject malformed suffix lengths instead of using parseInt
src/blob/utils/utils.ts:239
Validate the entire suffix length before accepting it. parseInt accepts malformed headers such as bytes=-1oops and bytes=-1,2 as one-byte suffixes, so a block blob containing abcdef returns 206 with f instead of reaching the existing invalid-range handling. Require decimal digits only, and add malformed-suffix regression cases.
…lper
Wrap Get Page Ranges range parsing in try/catch and map failures to
getInvalidPageRange. Restore RangePolicy to Range-only and give
InjectorPolicyFactory its own x-ms-range policy.
Reject malformed suffix ranges with trailing or fractional characters
src/blob/utils/utils.ts:239
parseInt accepts numeric prefixes, so malformed suffixes such as bytes=-3oops and bytes=-3.5 become valid three-byte ranges and are served as HTTP 206. Validate that the entire suffix contains decimal digits before accepting it, so these headers follow the existing invalid-range handling instead of silently selecting a different range.
… downloads
Get Page Ranges keeps upstream 200 for suffix/empty x-ms-range values and
still returns 416 for malformed ranges. Page blob Get Blob ignores
bytes=-0, bytes=-, and empty Range like block and append blobs.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Malformed suffixes still produce partial responses instead of using the invalid-range fallback.
No open issues 🎉
2 previously missed issues
In code that hasn't changed since last review
Reject malformed suffix ranges instead of truncating with parseInt
src/blob/utils/utils.ts:231
Malformed suffixes such as bytes=-1.5 and bytes=-1junk are accepted as bytes=-1 because parseInt stops at the first non-digit. Both download paths then return 206 with the last byte rather than using their invalid-range fallback (200 with the full blob). Validate the entire suffix as decimal digits before parsing, and add regression cases for these inputs.
Add multi-byte suffix download tests for exact ranges and clamping
src/blob/utils/utils.ts:287
The only successful suffix-download test uses a one-byte blob, so it cannot detect a resolver that always returns the whole blob. Add successful downloads with distinguishable multi-byte content for block, append, and populated page blobs. Cover suffix lengths smaller than and larger than the blob length, asserting the exact body, 206 status, and Content-Range to verify both offset calculation and clamping.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Get Blob with a suffix range on a 1-byte block blob returned HTTP 500 instead of 206.
Range: bytes=-1was parsed as startNaN, so Azurite loggedNormalizedDownloadRange=bytes=NaN-0and then threw aRangeError. Azure Storage returns 206 with the last byte (Content-Range: bytes 0-0/1).Fixes #2856
Fix
bytes=-Nwith N > 0) indeserializeRangeHeader, opt-in for downloads only (allowSuffixRangedefaults tofalse).bytes=-1,bytes=-99,bytes=-0,bytes=-,bytes=, empty) keep the upstream 200 (empty PageList). Malformed values such asbytes=5-2and garbage still return 416 rather than 500.bytes=-N(N > 0) on a 0-byte blob returns 416 withContent-Range: bytes */0on both the block/append download path and the page blob download path.bytes=-0,bytes=-,bytes=) is ignored like block and append blobs (HTTP 200, full body) instead of 500.ChangeLog.mdas required by this project's contribution guidelines.Test helper:
RangePolicyFactorysets only theRangeheader.InjectorPolicyFactoryhas its own policy that setsx-ms-rangeafter SDK serialization, so existing Range-header tests still exercise the plainRangeheader.Testing
Added coverage in
tests/blob/apis/blob.test.tsandtests/blob/apis/pageblob.test.ts.1-byte suffix download (unmodified upstream):
After the download suffix fix (nearby download/range tests):
0-byte suffix download and page-mutation suffix ranges (on 43914f2):
After opt-in suffix parsing and 0-byte 416:
Get Page Ranges and page-blob invalid Range (on d111d92, before this commit):
After restoring Get Page Ranges 200 and ignoring invalid page-blob download ranges:
loki suites (blob, pageblob, appendblob, blockblob, container, conditions) plus lint and tsc:
utils suite (no
@lokitags):This change was prepared with AI assistance. I remain responsible for the contribution and have reviewed it.