Skip to content

Commit

Permalink
[io/http] Don't add zero-valued content-length header on GET, HEAD, D…
Browse files Browse the repository at this point in the history
…ELETE, 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 #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>
  • Loading branch information
aam authored and commit-bot@chromium.org committed Jun 3, 2021
1 parent 2505b6c commit 6c254fa
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 18 deletions.
13 changes: 12 additions & 1 deletion sdk/lib/_http/http_headers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -503,8 +503,19 @@ class _HttpHeaders implements HttpHeaders {
_mutable = false;
}

void _build(BytesBuilder builder) {
void _build(BytesBuilder builder, {bool skipZeroContentLength = false}) {
// 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.
String? ignoreHeader = _contentLength == 0 && skipZeroContentLength
? HttpHeaders.contentLengthHeader
: null;
_headers.forEach((String name, List<String> values) {
if (ignoreHeader == name) {
return;
}
String originalName = _originalHeaderName(name);
bool fold = _foldHeader(name);
var nameData = originalName.codeUnits;
Expand Down
6 changes: 5 additions & 1 deletion sdk/lib/_http/http_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1583,7 +1583,11 @@ class _HttpClientRequest extends _HttpOutboundMessage<HttpClientResponse>
headers._finalize();

// Write headers.
headers._build(buffer);
headers._build(buffer,
skipZeroContentLength: method == "CONNECT" ||
method == "DELETE" ||
method == "GET" ||
method == "HEAD");
buffer.addByte(_CharCode.CR);
buffer.addByte(_CharCode.LF);
Uint8List headerBytes = buffer.takeBytes();
Expand Down
4 changes: 2 additions & 2 deletions tests/standalone/io/http_content_length_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ void testNoBody(int totalConnections, bool explicitContentLength) {
int count = 0;
HttpServer.bind("127.0.0.1", 0, backlog: totalConnections).then((server) {
server.listen((HttpRequest request) {
Expect.equals("0", request.headers.value('content-length'));
Expect.equals(0, request.contentLength);
Expect.equals(null, request.headers.value('content-length'));
Expect.equals(-1, request.contentLength);
var response = request.response;
response.contentLength = 0;
response.done.then((_) {
Expand Down
11 changes: 5 additions & 6 deletions tests/standalone/io/http_detach_socket_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,13 @@ void testClientDetachSocket() {
socket.listen((data) => body.write(new String.fromCharCodes(data)),
onDone: () {
List<String> lines = body.toString().split("\r\n");
Expect.equals(6, lines.length);
Expect.equals(5, lines.length);
Expect.equals("GET / HTTP/1.1", lines[0]);
Expect.equals("", lines[4]);
Expect.equals("Some data", lines[5]);
lines.sort(); // Lines 1-3 becomes 3-5 in a fixed order.
Expect.equals("", lines[3]);
Expect.equals("Some data", lines[4]);
lines.sort(); // Lines 1-2 becomes 3-4 in a fixed order.
Expect.equals("accept-encoding: gzip", lines[3]);
Expect.equals("content-length: 0", lines[4]);
Expect.equals("host: 127.0.0.1:${port}", lines[5]);
Expect.equals("host: 127.0.0.1:${port}", lines[4]);
socket.close();
});
server.close();
Expand Down
4 changes: 2 additions & 2 deletions tests/standalone_2/io/http_content_length_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ void testNoBody(int totalConnections, bool explicitContentLength) {
int count = 0;
HttpServer.bind("127.0.0.1", 0, backlog: totalConnections).then((server) {
server.listen((HttpRequest request) {
Expect.equals("0", request.headers.value('content-length'));
Expect.equals(0, request.contentLength);
Expect.equals(null, request.headers.value('content-length'));
Expect.equals(-1, request.contentLength);
var response = request.response;
response.contentLength = 0;
response.done.then((_) {
Expand Down
11 changes: 5 additions & 6 deletions tests/standalone_2/io/http_detach_socket_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,13 @@ void testClientDetachSocket() {
socket.listen((data) => body.write(new String.fromCharCodes(data)),
onDone: () {
List<String> lines = body.toString().split("\r\n");
Expect.equals(6, lines.length);
Expect.equals(5, lines.length);
Expect.equals("GET / HTTP/1.1", lines[0]);
Expect.equals("", lines[4]);
Expect.equals("Some data", lines[5]);
lines.sort(); // Lines 1-3 becomes 3-5 in a fixed order.
Expect.equals("", lines[3]);
Expect.equals("Some data", lines[4]);
lines.sort(); // Lines 1-2 becomes 3-4 in a fixed order.
Expect.equals("accept-encoding: gzip", lines[3]);
Expect.equals("content-length: 0", lines[4]);
Expect.equals("host: 127.0.0.1:${port}", lines[5]);
Expect.equals("host: 127.0.0.1:${port}", lines[4]);
socket.close();
});
server.close();
Expand Down

0 comments on commit 6c254fa

Please sign in to comment.