From e222f893cc971a4384dff468ecde43aeeae00f75 Mon Sep 17 00:00:00 2001 From: Joe Harlow Date: Tue, 14 Jun 2022 13:14:20 +0100 Subject: [PATCH 1/5] fix: kv:key put upload fix --- packages/wrangler/src/index.tsx | 2 +- packages/wrangler/src/kv.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/wrangler/src/index.tsx b/packages/wrangler/src/index.tsx index ed1730eaef4f..32cfcb0006e5 100644 --- a/packages/wrangler/src/index.tsx +++ b/packages/wrangler/src/index.tsx @@ -2260,7 +2260,7 @@ function createCLIParser(argv: string[]) { const namespaceId = getKVNamespaceId(args, config); // One of `args.path` and `args.value` must be defined const value = args.path - ? readFileSync(args.path) + ? fs.readFileSync(args.path) : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion args.value!; diff --git a/packages/wrangler/src/kv.ts b/packages/wrangler/src/kv.ts index a57adb67dcec..55da8f89922a 100644 --- a/packages/wrangler/src/kv.ts +++ b/packages/wrangler/src/kv.ts @@ -111,7 +111,7 @@ export async function deleteKVNamespace( */ export interface KeyValue { key: string; - value: string; + value: string | Buffer; expiration?: number; expiration_ttl?: number; metadata?: object; From 91e593a41208c34c815cdaa61df19ac5d1087e4f Mon Sep 17 00:00:00 2001 From: Joe Harlow Date: Tue, 14 Jun 2022 13:21:54 +0100 Subject: [PATCH 2/5] chore: catch the error reading the file --- packages/wrangler/src/index.tsx | 3 ++- packages/wrangler/src/parse.ts | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/packages/wrangler/src/index.tsx b/packages/wrangler/src/index.tsx index 32cfcb0006e5..c2bea0423a39 100644 --- a/packages/wrangler/src/index.tsx +++ b/packages/wrangler/src/index.tsx @@ -48,6 +48,7 @@ import { parsePackageJSON, parseTOML, readFileSync, + readFileSyncToBuffer, } from "./parse"; import publish from "./publish"; import { createR2Bucket, deleteR2Bucket, listR2Buckets } from "./r2"; @@ -2260,7 +2261,7 @@ function createCLIParser(argv: string[]) { const namespaceId = getKVNamespaceId(args, config); // One of `args.path` and `args.value` must be defined const value = args.path - ? fs.readFileSync(args.path) + ? readFileSyncToBuffer(args.path) : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion args.value!; diff --git a/packages/wrangler/src/parse.ts b/packages/wrangler/src/parse.ts index a84be84069f9..17a511b33ba7 100644 --- a/packages/wrangler/src/parse.ts +++ b/packages/wrangler/src/parse.ts @@ -139,6 +139,25 @@ export function parseJSON(input: string, file?: string): T { } } +/** + * Reads a file into a node Buffer. + */ +export function readFileSyncToBuffer(file: string): Buffer { + try { + return fs.readFileSync(file); + } catch (err) { + const { message } = err as Error; + throw new ParseError({ + text: `Could not read file: ${file}`, + notes: [ + { + text: message.replace(file, resolve(file)), + }, + ], + }); + } +} + /** * Reads a file and parses it based on its type. */ From f286c3c9171d30963d424c4ff6859920b4f90517 Mon Sep 17 00:00:00 2001 From: Joe Harlow Date: Tue, 14 Jun 2022 14:15:58 +0100 Subject: [PATCH 3/5] chore: fix previous test and implement binary test --- packages/wrangler/src/__tests__/kv.test.ts | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/packages/wrangler/src/__tests__/kv.test.ts b/packages/wrangler/src/__tests__/kv.test.ts index 543dba006bd8..d1698f1ade21 100644 --- a/packages/wrangler/src/__tests__/kv.test.ts +++ b/packages/wrangler/src/__tests__/kv.test.ts @@ -448,10 +448,11 @@ describe("wrangler", () => { }); it("should put a key with a value loaded from a given path", async () => { - writeFileSync("foo.txt", "file-contents", "utf-8"); + const buf = Buffer.from("file-contents", "utf-8"); + writeFileSync("foo.txt", buf); const requests = mockKeyPutRequest("some-namespace-id", { key: "my-key", - value: "file-contents", + value: buf, }); await runWrangler( "kv:key put my-key --namespace-id some-namespace-id --path foo.txt" @@ -463,6 +464,23 @@ describe("wrangler", () => { expect(requests.count).toEqual(1); }); + it("should put a key with a binary value loaded from a given path", async () => { + const buf = Buffer.from("iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAiSURBVHgB7coxEQAACMPAgH/PgAM6dGwu49fA/deIBXrgAj2cAhIFT4QxAAAAAElFTkSuQmCC", "base64"); + writeFileSync("test.png", buf); + const requests = mockKeyPutRequest("another-namespace-id", { + key: "my-key", + value: buf, + }); + await runWrangler( + "kv:key put my-key --namespace-id another-namespace-id --path test.png" + ); + expect(std.out).toMatchInlineSnapshot( + `"Writing the contents of test.png to the key \\"my-key\\" on namespace another-namespace-id."` + ); + expect(std.err).toMatchInlineSnapshot(`""`); + expect(requests.count).toEqual(1); + }); + it("should error if no key is provided", async () => { await expect( runWrangler("kv:key put") From 9b62f683e5d0241971dcfaf5ad836bdfc3a3449b Mon Sep 17 00:00:00 2001 From: Joe Harlow Date: Tue, 14 Jun 2022 14:24:19 +0100 Subject: [PATCH 4/5] chore: provide changeset --- .changeset/curly-lizards-rescue.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/curly-lizards-rescue.md diff --git a/.changeset/curly-lizards-rescue.md b/.changeset/curly-lizards-rescue.md new file mode 100644 index 000000000000..c645e2ae4b64 --- /dev/null +++ b/.changeset/curly-lizards-rescue.md @@ -0,0 +1,7 @@ +--- +"wrangler": patch +--- + +fix: kv:key put binary file upload + +As raised in https://github.com/cloudflare/wrangler2/issues/1254, it was discovered that binary uploads were being mangled by wrangler 2, whereas they worked in wrangler 1. This is because they were read into a string by providing an explicit encoding of `utf-8`. This fix reads provided files into a node `Buffer` that is then passed directly to the request. From dfef5e88e4d0687466bb79dcc1498c4f0235b69b Mon Sep 17 00:00:00 2001 From: Joe Harlow Date: Tue, 14 Jun 2022 14:33:25 +0100 Subject: [PATCH 5/5] chore: run prettier on kv.test.ts --- packages/wrangler/src/__tests__/kv.test.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/wrangler/src/__tests__/kv.test.ts b/packages/wrangler/src/__tests__/kv.test.ts index d1698f1ade21..bb343a9393f3 100644 --- a/packages/wrangler/src/__tests__/kv.test.ts +++ b/packages/wrangler/src/__tests__/kv.test.ts @@ -465,7 +465,10 @@ describe("wrangler", () => { }); it("should put a key with a binary value loaded from a given path", async () => { - const buf = Buffer.from("iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAiSURBVHgB7coxEQAACMPAgH/PgAM6dGwu49fA/deIBXrgAj2cAhIFT4QxAAAAAElFTkSuQmCC", "base64"); + const buf = Buffer.from( + "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAiSURBVHgB7coxEQAACMPAgH/PgAM6dGwu49fA/deIBXrgAj2cAhIFT4QxAAAAAElFTkSuQmCC", + "base64" + ); writeFileSync("test.png", buf); const requests = mockKeyPutRequest("another-namespace-id", { key: "my-key",