diff --git a/packages/r2/src/r2Object.ts b/packages/r2/src/r2Object.ts index 62d85ef32..e3f6ebdfc 100644 --- a/packages/r2/src/r2Object.ts +++ b/packages/r2/src/r2Object.ts @@ -164,10 +164,17 @@ function matchStrings(a: string | string[], b: string): boolean { } // headers can be a list: e.g. ["if-match", "a, b, c"] -> "if-match: [a, b, c]" -function parseHeaderArray(input?: string): undefined | string | string[] { - if (typeof input !== "string") return; - if (!input.includes(",")) return input; - return input.split(",").map((x) => x.trim()); +function parseHeaderArray(input: string): string | string[] { + // split if comma found, otherwise return input + if (!input.includes(",")) return stripQuotes(input); + return input.split(",").map((x) => stripQuotes(x)); +} + +function stripQuotes(input: string): string { + input = input.trim(); + if (input[0] === '"') input = input.slice(1); + if (input[input.length - 1] === '"') input = input.slice(0, -1); + return input; } export function parseOnlyIf( @@ -185,18 +192,26 @@ export function parseOnlyIf( // if string list, convert to array. e.g. 'etagMatches': 'a, b, c' -> ['a', 'b', 'c'] if (typeof onlyIf.etagMatches === "string") { onlyIf.etagMatches = parseHeaderArray(onlyIf.etagMatches); + } else if (Array.isArray(onlyIf.etagMatches)) { + // otherwise if an array, strip the quotes + onlyIf.etagMatches = onlyIf.etagMatches.map((x) => stripQuotes(x)); } // if string list, convert to array. e.g. 'etagMatches': 'a, b, c' -> ['a', 'b', 'c'] if (typeof onlyIf.etagDoesNotMatch === "string") { onlyIf.etagDoesNotMatch = parseHeaderArray(onlyIf.etagDoesNotMatch); + } else if (Array.isArray(onlyIf.etagDoesNotMatch)) { + // otherwise if an array, strip the quotes + onlyIf.etagDoesNotMatch = onlyIf.etagDoesNotMatch.map((x) => + stripQuotes(x) + ); } // if string, convert to date if (typeof onlyIf.uploadedBefore === "string") { - onlyIf.uploadedBefore = new Date(onlyIf.uploadedBefore); + onlyIf.uploadedBefore = new Date(stripQuotes(onlyIf.uploadedBefore)); } // if string, convert to date if (typeof onlyIf.uploadedAfter === "string") { - onlyIf.uploadedAfter = new Date(onlyIf.uploadedAfter); + onlyIf.uploadedAfter = new Date(stripQuotes(onlyIf.uploadedAfter)); } return onlyIf as R2Conditional; diff --git a/packages/r2/test/r2Object.spec.ts b/packages/r2/test/r2Object.spec.ts index 8d37a0231..dd9481206 100644 --- a/packages/r2/test/r2Object.spec.ts +++ b/packages/r2/test/r2Object.spec.ts @@ -427,6 +427,20 @@ test("R2Object: parseOnlyIf: each parameter is parsed correctly as an R2Conditio t.deepEqual(parsed.uploadedAfter, new Date(0)); }); +test("R2Object: parseOnlyIf with quotes: each parameter is parsed correctly as an R2Conditional object", (t) => { + const r2conditional = { + etagMatches: '"*"', + etagDoesNotMatch: ['"123"', '"456"'], + uploadedBefore: '"1970-01-01T00:00:00.000Z"', + uploadedAfter: '"1970-01-01T00:00:00.000Z"', + }; + const parsed = parseOnlyIf(r2conditional as any); + t.is(parsed.etagMatches, "*"); + t.deepEqual(parsed.etagDoesNotMatch, ["123", "456"]); + t.deepEqual(parsed.uploadedBefore, new Date(0)); + t.deepEqual(parsed.uploadedAfter, new Date(0)); +}); + test("R2Object: parseOnlyIf: parsing instanceof Headers", (t) => { const r2ConditionalHeaders = new Headers(); // test capitalization