Skip to content

Commit

Permalink
fix(ext/formdata): support multiple headers in FormData
Browse files Browse the repository at this point in the history
  • Loading branch information
marcosc90 committed Oct 5, 2023
1 parent 1619932 commit 2f5c1b7
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 16 deletions.
32 changes: 32 additions & 0 deletions cli/tests/unit/body_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,35 @@ Deno.test(async function bodyArrayBufferMultipleParts() {
const body = buildBody(stream);
assertEquals((await body.arrayBuffer()).byteLength, size);
});

// https://github.com/denoland/deno/issues/20793
Deno.test(
{ permissions: { net: true } },
async function bodyMultipartFormDataMultipleHeaders() {
const boundary = "----formdata-polyfill-0.970665446687947";
const payload = [
"------formdata-polyfill-0.970665446687947",
'Content-Disposition: form-data; name="x"; filename="blob"',
"Content-Length: 1",
"Content-Type: application/octet-stream",
"last-modified: Wed, 04 Oct 2023 20:28:45 GMT",
"",
"y",
"------formdata-polyfill-0.970665446687947--",
].join("\r\n");

const body = buildBody(
new TextEncoder().encode(payload),
new Headers({
"Content-Type": `multipart/form-data; boundary=${boundary}`,
}),
);

const formData = await body.formData();
const file = formData.get("x");
assert(file instanceof File);
const text = await file.text();
assertEquals(text, "y");
assertEquals(file.size, 1);
},
);
30 changes: 14 additions & 16 deletions ext/fetch/21_formdata.js
Original file line number Diff line number Diff line change
Expand Up @@ -448,25 +448,23 @@ class MultipartParser {
const prevByte = this.body[i - 1];
const isNewLine = byte === LF && prevByte === CR;

if (state === 1 || state === 2 || state == 3) {
if (state === 1) {
headerText += StringFromCharCode(byte);
}

if (state === 0 && isNewLine) {
state = 1;
} else if (state === 1 && isNewLine) {
state = 2;
const headersDone = this.body[i + 1] === CR &&
this.body[i + 2] === LF;

if (headersDone) {
state = 3;
} else if (
state === 1
) {
if (
isNewLine && this.body[i + 1] === CR &&
this.body[i + 2] === LF
) {
state = 2;
fileStart = i + 3; // After \r\n
}
} else if (state === 2 && isNewLine) {
state = 3;
} else if (state === 3 && isNewLine) {
state = 4;
fileStart = i + 1;
} else if (state === 4) {
} else if (state === 2) {
if (this.boundaryChars[boundaryIndex] !== byte) {
boundaryIndex = 0;
} else {
Expand All @@ -487,7 +485,7 @@ class MultipartParser {
const latin1Filename = MapPrototypeGet(disposition, "filename");
const latin1Name = MapPrototypeGet(disposition, "name");

state = 5;
state = 3;
// Reset
boundaryIndex = 0;
headerText = "";
Expand All @@ -510,7 +508,7 @@ class MultipartParser {
formData.append(name, core.decode(content));
}
}
} else if (state === 5 && isNewLine) {
} else if (state === 3 && isNewLine) {
state = 1;
}
}
Expand Down

0 comments on commit 2f5c1b7

Please sign in to comment.