From 24f7f3fda984e7226b5858085a7ed1c53ab081e0 Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Tue, 23 Aug 2022 12:43:04 +0200 Subject: [PATCH] fix(ext/fetch): ignore user content-length header (#15555) Previously if a user specified a content-length header for an POST request without a body, the request would contain two `content-length` headers. One added by us, and one added by the user. This commit ignores all content-length headers coming from the user, because we need to have the sole authority on the content-length because we transmit the body. --- cli/tests/unit/fetch_test.ts | 62 ++++++++++++++++++++++++++++++++++++ ext/fetch/lib.rs | 2 +- 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/cli/tests/unit/fetch_test.ts b/cli/tests/unit/fetch_test.ts index 6408d06d34..175431e76b 100644 --- a/cli/tests/unit/fetch_test.ts +++ b/cli/tests/unit/fetch_test.ts @@ -760,6 +760,68 @@ Deno.test( }, ); +Deno.test( + { + permissions: { net: true }, + }, + async function fetchUserSetContentLength() { + const addr = "127.0.0.1:4501"; + const bufPromise = bufferServer(addr); + const response = await fetch(`http://${addr}/blah`, { + method: "POST", + headers: [ + ["Content-Length", "10"], + ], + }); + await response.arrayBuffer(); + assertEquals(response.status, 404); + assertEquals(response.headers.get("Content-Length"), "2"); + + const actual = new TextDecoder().decode((await bufPromise).bytes()); + const expected = [ + "POST /blah HTTP/1.1\r\n", + "content-length: 0\r\n", + "accept: */*\r\n", + "accept-language: *\r\n", + `user-agent: Deno/${Deno.version.deno}\r\n`, + "accept-encoding: gzip, br\r\n", + `host: ${addr}\r\n\r\n`, + ].join(""); + assertEquals(actual, expected); + }, +); + +Deno.test( + { + permissions: { net: true }, + }, + async function fetchUserSetTransferEncoding() { + const addr = "127.0.0.1:4501"; + const bufPromise = bufferServer(addr); + const response = await fetch(`http://${addr}/blah`, { + method: "POST", + headers: [ + ["Transfer-Encoding", "chunked"], + ], + }); + await response.arrayBuffer(); + assertEquals(response.status, 404); + assertEquals(response.headers.get("Content-Length"), "2"); + + const actual = new TextDecoder().decode((await bufPromise).bytes()); + const expected = [ + "POST /blah HTTP/1.1\r\n", + "content-length: 0\r\n", + `host: ${addr}\r\n`, + "accept: */*\r\n", + "accept-language: *\r\n", + `user-agent: Deno/${Deno.version.deno}\r\n`, + "accept-encoding: gzip, br\r\n\r\n", + ].join(""); + assertEquals(actual, expected); + }, +); + Deno.test( { permissions: { net: true }, diff --git a/ext/fetch/lib.rs b/ext/fetch/lib.rs index 232e6964e0..20db7abbc9 100644 --- a/ext/fetch/lib.rs +++ b/ext/fetch/lib.rs @@ -287,7 +287,7 @@ where .map_err(|err| type_error(err.to_string()))?; let v = HeaderValue::from_bytes(&value) .map_err(|err| type_error(err.to_string()))?; - if name != HOST { + if !matches!(name, HOST | CONTENT_LENGTH) { request = request.header(name, v); } }