|
1 | 1 | import { z } from "zod"; |
2 | 2 | import { Log } from "../../shared"; |
3 | 3 | import { RangeStoredValueMeta, Storage } from "../../storage"; |
| 4 | +import { _parseRanges } from "../shared"; |
4 | 5 | import { InvalidRange, NoSuchKey } from "./errors"; |
5 | 6 | import { |
6 | 7 | R2Object, |
@@ -59,12 +60,26 @@ export class R2Gateway { |
59 | 60 | key: string, |
60 | 61 | options: R2GetOptions = {} |
61 | 62 | ): Promise<R2ObjectBody | R2Object> { |
62 | | - const { range = {}, onlyIf } = options; |
63 | | - validate.key(key).condition(await this.head(key), onlyIf); |
| 63 | + const meta = await this.head(key); |
| 64 | + validate.key(key).condition(meta, options.onlyIf); |
| 65 | + |
| 66 | + let range = options.range ?? {}; |
| 67 | + if (options.rangeHeader !== undefined) { |
| 68 | + const ranges = _parseRanges(options.rangeHeader, meta.size); |
| 69 | + if (ranges?.length === 1) { |
| 70 | + // If the header contained a single range, convert it to an R2Range. |
| 71 | + // Note `start` and `end` are inclusive. |
| 72 | + const [start, end] = ranges[0]; |
| 73 | + range = { offset: start, length: end - start + 1 }; |
| 74 | + } else { |
| 75 | + // If the header was invalid, or contained multiple ranges, just return |
| 76 | + // the full response |
| 77 | + range = {}; |
| 78 | + } |
| 79 | + } |
64 | 80 |
|
65 | 81 | let stored: RangeStoredValueMeta<R2ObjectMetadata> | undefined; |
66 | 82 |
|
67 | | - // get data dependent upon whether suffix or range exists |
68 | 83 | try { |
69 | 84 | stored = await this.storage.getRange<R2ObjectMetadata>(key, range); |
70 | 85 | } catch { |
|
0 commit comments