Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 6c254fa

Browse files
aamcommit-bot@chromium.org
authored andcommitted
[io/http] Don't add zero-valued content-length header on GET, HEAD, DELETE, CONNECT requests.
Per https://tools.ietf.org/html/rfc7230#section-3.3.2: "... A user agent SHOULD NOT send a Content-Length header field when the request message does not contain a payload body and the method semantics do not anticipate such a body." Fixes dart-lang/sdk#45139 Change-Id: I96b735c06038eb3d12a303ee5329228a9b594726 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/194881 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Siva Annamalai <asiva@google.com> Reviewed-by: Lasse R.H. Nielsen <lrn@google.com>
1 parent 2505b6c commit 6c254fa

File tree

6 files changed

+31
-18
lines changed

6 files changed

+31
-18
lines changed

sdk/lib/_http/http_headers.dart

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,8 +503,19 @@ class _HttpHeaders implements HttpHeaders {
503503
_mutable = false;
504504
}
505505

506-
void _build(BytesBuilder builder) {
506+
void _build(BytesBuilder builder, {bool skipZeroContentLength = false}) {
507+
// per https://tools.ietf.org/html/rfc7230#section-3.3.2
508+
// A user agent SHOULD NOT send a
509+
// Content-Length header field when the request message does not
510+
// contain a payload body and the method semantics do not anticipate
511+
// such a body.
512+
String? ignoreHeader = _contentLength == 0 && skipZeroContentLength
513+
? HttpHeaders.contentLengthHeader
514+
: null;
507515
_headers.forEach((String name, List<String> values) {
516+
if (ignoreHeader == name) {
517+
return;
518+
}
508519
String originalName = _originalHeaderName(name);
509520
bool fold = _foldHeader(name);
510521
var nameData = originalName.codeUnits;

sdk/lib/_http/http_impl.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1583,7 +1583,11 @@ class _HttpClientRequest extends _HttpOutboundMessage<HttpClientResponse>
15831583
headers._finalize();
15841584

15851585
// Write headers.
1586-
headers._build(buffer);
1586+
headers._build(buffer,
1587+
skipZeroContentLength: method == "CONNECT" ||
1588+
method == "DELETE" ||
1589+
method == "GET" ||
1590+
method == "HEAD");
15871591
buffer.addByte(_CharCode.CR);
15881592
buffer.addByte(_CharCode.LF);
15891593
Uint8List headerBytes = buffer.takeBytes();

tests/standalone/io/http_content_length_test.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ void testNoBody(int totalConnections, bool explicitContentLength) {
1616
int count = 0;
1717
HttpServer.bind("127.0.0.1", 0, backlog: totalConnections).then((server) {
1818
server.listen((HttpRequest request) {
19-
Expect.equals("0", request.headers.value('content-length'));
20-
Expect.equals(0, request.contentLength);
19+
Expect.equals(null, request.headers.value('content-length'));
20+
Expect.equals(-1, request.contentLength);
2121
var response = request.response;
2222
response.contentLength = 0;
2323
response.done.then((_) {

tests/standalone/io/http_detach_socket_test.dart

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,13 @@ void testClientDetachSocket() {
110110
socket.listen((data) => body.write(new String.fromCharCodes(data)),
111111
onDone: () {
112112
List<String> lines = body.toString().split("\r\n");
113-
Expect.equals(6, lines.length);
113+
Expect.equals(5, lines.length);
114114
Expect.equals("GET / HTTP/1.1", lines[0]);
115-
Expect.equals("", lines[4]);
116-
Expect.equals("Some data", lines[5]);
117-
lines.sort(); // Lines 1-3 becomes 3-5 in a fixed order.
115+
Expect.equals("", lines[3]);
116+
Expect.equals("Some data", lines[4]);
117+
lines.sort(); // Lines 1-2 becomes 3-4 in a fixed order.
118118
Expect.equals("accept-encoding: gzip", lines[3]);
119-
Expect.equals("content-length: 0", lines[4]);
120-
Expect.equals("host: 127.0.0.1:${port}", lines[5]);
119+
Expect.equals("host: 127.0.0.1:${port}", lines[4]);
121120
socket.close();
122121
});
123122
server.close();

tests/standalone_2/io/http_content_length_test.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ void testNoBody(int totalConnections, bool explicitContentLength) {
1818
int count = 0;
1919
HttpServer.bind("127.0.0.1", 0, backlog: totalConnections).then((server) {
2020
server.listen((HttpRequest request) {
21-
Expect.equals("0", request.headers.value('content-length'));
22-
Expect.equals(0, request.contentLength);
21+
Expect.equals(null, request.headers.value('content-length'));
22+
Expect.equals(-1, request.contentLength);
2323
var response = request.response;
2424
response.contentLength = 0;
2525
response.done.then((_) {

tests/standalone_2/io/http_detach_socket_test.dart

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,13 @@ void testClientDetachSocket() {
112112
socket.listen((data) => body.write(new String.fromCharCodes(data)),
113113
onDone: () {
114114
List<String> lines = body.toString().split("\r\n");
115-
Expect.equals(6, lines.length);
115+
Expect.equals(5, lines.length);
116116
Expect.equals("GET / HTTP/1.1", lines[0]);
117-
Expect.equals("", lines[4]);
118-
Expect.equals("Some data", lines[5]);
119-
lines.sort(); // Lines 1-3 becomes 3-5 in a fixed order.
117+
Expect.equals("", lines[3]);
118+
Expect.equals("Some data", lines[4]);
119+
lines.sort(); // Lines 1-2 becomes 3-4 in a fixed order.
120120
Expect.equals("accept-encoding: gzip", lines[3]);
121-
Expect.equals("content-length: 0", lines[4]);
122-
Expect.equals("host: 127.0.0.1:${port}", lines[5]);
121+
Expect.equals("host: 127.0.0.1:${port}", lines[4]);
123122
socket.close();
124123
});
125124
server.close();

0 commit comments

Comments
 (0)