Skip to content

Commit

Permalink
fix(fetch): set content-length for empty POST/PUT (denoland#12703)
Browse files Browse the repository at this point in the history
This commit changes `fetch` to set `content-length: 0` on POST and PUT
requests with no body.
  • Loading branch information
lucacasonato committed Nov 9, 2021
1 parent 75793ba commit 0de6d1e
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 1 deletion.
58 changes: 58 additions & 0 deletions cli/tests/unit/fetch_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,7 @@ unitTest(
const actual = new TextDecoder().decode((await bufPromise).bytes());
const expected = [
"POST /blah HTTP/1.1\r\n",
"content-length: 0\r\n",
"hello: World\r\n",
"foo: Bar\r\n",
"accept: */*\r\n",
Expand Down Expand Up @@ -1416,3 +1417,60 @@ unitTest(
assertEquals(await res.text(), fixture);
},
);

unitTest(
{ permissions: { net: true } },
async function fetchContentLengthPost() {
const response = await fetch("http:https://localhost:4545/content_length", {
method: "POST",
});
const length = await response.text();
assertEquals(length, 'Some("0")');
},
);

unitTest(
{ permissions: { net: true } },
async function fetchContentLengthPut() {
const response = await fetch("http:https://localhost:4545/content_length", {
method: "PUT",
});
const length = await response.text();
assertEquals(length, 'Some("0")');
},
);

unitTest(
{ permissions: { net: true } },
async function fetchContentLengthPatch() {
const response = await fetch("http:https://localhost:4545/content_length", {
method: "PATCH",
});
const length = await response.text();
assertEquals(length, "None");
},
);

unitTest(
{ permissions: { net: true } },
async function fetchContentLengthPostWithStringBody() {
const response = await fetch("http:https://localhost:4545/content_length", {
method: "POST",
body: "Hey!",
});
const length = await response.text();
assertEquals(length, 'Some("4")');
},
);

unitTest(
{ permissions: { net: true } },
async function fetchContentLengthPostWithBufferBody() {
const response = await fetch("http:https://localhost:4545/content_length", {
method: "POST",
body: new TextEncoder().encode("Hey!"),
});
const length = await response.text();
assertEquals(length, 'Some("4")');
},
);
7 changes: 6 additions & 1 deletion ext/fetch/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ where
let permissions = state.borrow_mut::<FP>();
permissions.check_net_url(&url)?;

let mut request = client.request(method, url);
let mut request = client.request(method.clone(), url);

let request_body_rid = if args.has_body {
match data {
Expand Down Expand Up @@ -278,6 +278,11 @@ where
}
}
} else {
// POST and PUT requests should always have a 0 length content-length,
// if there is no body. https://fetch.spec.whatwg.org/#http-network-or-cache-fetch
if matches!(method, Method::POST | Method::PUT) {
request = request.header(CONTENT_LENGTH, HeaderValue::from(0));
}
None
};

Expand Down
4 changes: 4 additions & 0 deletions test_util/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,10 @@ async fn main_server(
let version = format!("{:?}", req.version());
Ok(Response::new(version.into()))
}
(_, "/content_length") => {
let content_length = format!("{:?}", req.headers().get("content-length"));
Ok(Response::new(content_length.into()))
}
(_, "/jsx/jsx-runtime") | (_, "/jsx/jsx-dev-runtime") => {
let mut res = Response::new(Body::from(
r#"export function jsx(
Expand Down

0 comments on commit 0de6d1e

Please sign in to comment.