diff options
author | Luca Casonato <hello@lcas.dev> | 2022-08-23 12:43:04 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-23 12:43:04 +0200 |
commit | 24f7f3fda984e7226b5858085a7ed1c53ab081e0 (patch) | |
tree | c72348b71d68ea200644e8a07806d1ba9888a8a6 | |
parent | ecf3b51fd93c36f10e7ce53e961bdeca449a955f (diff) |
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.
-rw-r--r-- | cli/tests/unit/fetch_test.ts | 62 | ||||
-rw-r--r-- | ext/fetch/lib.rs | 2 |
2 files changed, 63 insertions, 1 deletions
diff --git a/cli/tests/unit/fetch_test.ts b/cli/tests/unit/fetch_test.ts index 6408d06d3..175431e76 100644 --- a/cli/tests/unit/fetch_test.ts +++ b/cli/tests/unit/fetch_test.ts @@ -764,6 +764,68 @@ 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 }, + }, async function fetchWithNonAsciiRedirection() { const response = await fetch("http://localhost:4545/non_ascii_redirect", { redirect: "manual", diff --git a/ext/fetch/lib.rs b/ext/fetch/lib.rs index 232e6964e..20db7abbc 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); } } |