mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 10:18:13 +00:00
6c254fab89
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 https://github.com/dart-lang/sdk/issues/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>
200 lines
6 KiB
Dart
200 lines
6 KiB
Dart
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
//
|
|
// VMOptions=
|
|
// VMOptions=--short_socket_read
|
|
// VMOptions=--short_socket_write
|
|
// VMOptions=--short_socket_read --short_socket_write
|
|
|
|
// @dart = 2.9
|
|
|
|
import "package:expect/expect.dart";
|
|
import "package:async_helper/async_helper.dart";
|
|
import "dart:io";
|
|
import "dart:isolate";
|
|
|
|
void testServerDetachSocket() {
|
|
HttpServer.bind("127.0.0.1", 0).then((server) {
|
|
server.defaultResponseHeaders.clear();
|
|
server.serverHeader = null;
|
|
server.listen((request) {
|
|
var response = request.response;
|
|
response.contentLength = 0;
|
|
response.detachSocket().then((socket) {
|
|
Expect.isNotNull(socket);
|
|
var body = new StringBuffer();
|
|
socket.listen((data) => body.write(new String.fromCharCodes(data)),
|
|
onDone: () => Expect.equals("Some data", body.toString()));
|
|
socket.write("Test!");
|
|
socket.close();
|
|
});
|
|
server.close();
|
|
});
|
|
|
|
Socket.connect("127.0.0.1", server.port).then((socket) {
|
|
socket.write("GET / HTTP/1.1\r\n"
|
|
"content-length: 0\r\n\r\n"
|
|
"Some data");
|
|
var body = new StringBuffer();
|
|
socket.listen((data) => body.write(new String.fromCharCodes(data)),
|
|
onDone: () {
|
|
Expect.equals(
|
|
"HTTP/1.1 200 OK\r\n"
|
|
"content-length: 0\r\n"
|
|
"\r\n"
|
|
"Test!",
|
|
body.toString());
|
|
socket.close();
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
void testServerDetachSocketNoWriteHeaders() {
|
|
HttpServer.bind("127.0.0.1", 0).then((server) {
|
|
server.listen((request) {
|
|
var response = request.response;
|
|
response.contentLength = 0;
|
|
response.detachSocket(writeHeaders: false).then((socket) {
|
|
Expect.isNotNull(socket);
|
|
var body = new StringBuffer();
|
|
socket.listen((data) => body.write(new String.fromCharCodes(data)),
|
|
onDone: () => Expect.equals("Some data", body.toString()));
|
|
socket.write("Test!");
|
|
socket.close();
|
|
});
|
|
server.close();
|
|
});
|
|
|
|
Socket.connect("127.0.0.1", server.port).then((socket) {
|
|
socket.write("GET / HTTP/1.1\r\n"
|
|
"content-length: 0\r\n\r\n"
|
|
"Some data");
|
|
var body = new StringBuffer();
|
|
socket.listen((data) => body.write(new String.fromCharCodes(data)),
|
|
onDone: () {
|
|
Expect.equals("Test!", body.toString());
|
|
socket.close();
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
void testBadServerDetachSocket() {
|
|
HttpServer.bind("127.0.0.1", 0).then((server) {
|
|
server.listen((request) {
|
|
var response = request.response;
|
|
response.contentLength = 0;
|
|
response.close();
|
|
Expect.throws(response.detachSocket);
|
|
server.close();
|
|
});
|
|
|
|
Socket.connect("127.0.0.1", server.port).then((socket) {
|
|
socket.write("GET / HTTP/1.1\r\n"
|
|
"content-length: 0\r\n\r\n");
|
|
socket.listen((_) {}, onDone: () {
|
|
socket.close();
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
void testClientDetachSocket() {
|
|
ServerSocket.bind("127.0.0.1", 0).then((server) {
|
|
server.listen((socket) {
|
|
int port = server.port;
|
|
socket.write("HTTP/1.1 200 OK\r\n"
|
|
"\r\n"
|
|
"Test!");
|
|
var body = new StringBuffer();
|
|
socket.listen((data) => body.write(new String.fromCharCodes(data)),
|
|
onDone: () {
|
|
List<String> lines = body.toString().split("\r\n");
|
|
Expect.equals(5, lines.length);
|
|
Expect.equals("GET / HTTP/1.1", lines[0]);
|
|
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("host: 127.0.0.1:${port}", lines[4]);
|
|
socket.close();
|
|
});
|
|
server.close();
|
|
});
|
|
|
|
var client = new HttpClient();
|
|
client.userAgent = null;
|
|
client
|
|
.get("127.0.0.1", server.port, "/")
|
|
.then((request) => request.close())
|
|
.then((response) {
|
|
response.detachSocket().then((socket) {
|
|
var body = new StringBuffer();
|
|
socket.listen((data) => body.write(new String.fromCharCodes(data)),
|
|
onDone: () {
|
|
Expect.equals("Test!", body.toString());
|
|
client.close();
|
|
});
|
|
socket.write("Some data");
|
|
socket.close();
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
void testUpgradedConnection() {
|
|
asyncStart();
|
|
HttpServer.bind("127.0.0.1", 0).then((server) {
|
|
server.listen((request) {
|
|
request.response.headers.set('connection', 'upgrade');
|
|
if (request.headers.value('upgrade') == 'mine') {
|
|
asyncStart();
|
|
request.response.detachSocket().then((socket) {
|
|
socket.cast<List<int>>().pipe(socket).then((_) {
|
|
asyncEnd();
|
|
});
|
|
});
|
|
} else {
|
|
request.response.close();
|
|
}
|
|
});
|
|
|
|
var client = new HttpClient();
|
|
client.userAgent = null;
|
|
client.get("127.0.0.1", server.port, "/").then((request) {
|
|
request.headers.set('upgrade', 'mine');
|
|
return request.close();
|
|
}).then((response) {
|
|
client.get("127.0.0.1", server.port, "/").then((request) {
|
|
response.detachSocket().then((socket) {
|
|
// We are testing that we can detach the socket, even though
|
|
// we made a new connection (testing it was not reused).
|
|
request.close().then((response) {
|
|
asyncStart();
|
|
response.listen(null, onDone: () {
|
|
server.close();
|
|
asyncEnd();
|
|
});
|
|
socket.add([0]);
|
|
socket.close();
|
|
socket.fold([], (l, d) => l..addAll(d)).then((data) {
|
|
asyncEnd();
|
|
Expect.listEquals([0], data);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
void main() {
|
|
testServerDetachSocket();
|
|
testServerDetachSocketNoWriteHeaders();
|
|
testBadServerDetachSocket();
|
|
testClientDetachSocket();
|
|
testUpgradedConnection();
|
|
}
|