Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

馃悰 BUG: wrangler kv:key put does not work as expected #2911

Closed
vilvei opened this issue Mar 17, 2023 · 3 comments 路 Fixed by #5619
Closed

馃悰 BUG: wrangler kv:key put does not work as expected #2911

vilvei opened this issue Mar 17, 2023 · 3 comments 路 Fixed by #5619
Labels
bug Something that isn't working

Comments

@vilvei
Copy link

vilvei commented Mar 17, 2023

Which Cloudflare product(s) does this pertain to?

KV, Wrangler

What version of Wrangler are you using?

2.12.3

What operating system are you using?

Linux

Describe the Bug

wrangler kv:key put does not work as expected when using --path with --metadata commandline options.
Meaning of "as expected": the same bytes can not be read with kv:key get, that were previously put.

Simple way to test:

This works: the same file can be get, which were put:
md5 original.png
81a3478c5f2b12823f3ff0253c3388e7
wrangler kv:key put --binding=FILES kvimage.png --path=original.png
wrangler kv:key get --binding=FILES kvimage.png > copy.png
md5 copy.png
81a3478c5f2b12823f3ff0253c3388e7

This does NOT work, md5 does not match, the bytes are different:
md5 original.png
81a3478c5f2b12823f3ff0253c3388e7
wrangler kv:key put --binding=FILES kvimage.png --path=original.png --metadata='{"contentType":"image/png"}'
wrangler kv:key get --binding=FILES kvimage.png > copy.png
md5 copy.png
40621887293ab018c535120fe0b6bf92

Looking code:

I think the problem is that wrangler is putting the Buffer data into FormData, to be sent to KV. And this is a wrong type of data to be added into FormData.

--path file is read with readFileSyncToBuffer, which returns node-Buffer
https://github.com/cloudflare/workers-sdk/blob/main/packages/wrangler/src/kv/index.ts#L236

This is given to function putKVKeyValue
https://github.com/cloudflare/workers-sdk/blob/main/packages/wrangler/src/kv/helpers.ts#L203

which tries to append the Buffer into undici FormData object.
https://github.com/cloudflare/workers-sdk/blob/main/packages/wrangler/src/kv/helpers.ts#L193

undici FormData append expects value to be eg. Blob or File, but receives Buffer. So Buffer is converted to string.
https://github.com/nodejs/undici/blob/main/types/formdata.d.ts#L27

@vilvei vilvei added the bug Something that isn't working label Mar 17, 2023
@vilvei
Copy link
Author

vilvei commented Mar 17, 2023

The cleanest way to fix this, is to send metadata in PUT-headers: KV can hold only a very small size of metadata-data anyway, so this would not brake anything on storing data.
This also enables the value always to be sent as PUT-body. Which also might help to deliver filedata as ReadStream on PUT-body, instead of potentially 25MB of Buffer in memory.

@vilvei vilvei changed the title 馃悰 BUG: 馃悰 BUG: wrangler kv:key put breaks file when using --path with --metadata commandline Mar 17, 2023
@rozenmd rozenmd changed the title 馃悰 BUG: wrangler kv:key put breaks file when using --path with --metadata commandline 馃悰 BUG: wrangler kv:key put does not work as expected Mar 17, 2023
@scottmas
Copy link

scottmas commented Jan 9, 2024

Can verify this is happening. Had me utterly stumped for a long while.

@gmemstr
Copy link
Contributor

gmemstr commented Apr 15, 2024

Linking the culprit with a specific commit hash so it doesn't move around when the file is modified :)

function asFormData(fields: Record<string, unknown>): FormData {
const formData = new FormData();
for (const [name, value] of Object.entries(fields)) {
formData.append(name, value);
}
return formData;
}

I think we can get away with checking if the type is a Buffer, and if so, convert it? Something like

function asFormData(fields: Record<string, unknown>): FormData {
	const formData = new FormData();

	for (let [name, value] of Object.entries(fields)) {
                if (Buffer.isBuffer(value)) {
                    value = new Blob([value]);
                }
		formData.append(name, value);
	}

	return formData;
}

Maybe there's a more elegant way of doing it, but I'll open a PR with this change to at least get things moving in the right direction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something that isn't working
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

5 participants