Migrate standalone tests which rely on the pre-nnbd sdk libraries.

Migrate all the tests under standalone/ that include files under
sdk/sdk/ as part files to unblock the replacement of the unmigrated
sdk/sdk with the contents of the migrated sdk/sdk_nnbd.

Change-Id: Ia2e78bbff797f58244d94021d4b9616793bd641d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151036
Commit-Queue: Leaf Petersen <leafp@google.com>
Reviewed-by: Lasse R.H. Nielsen <lrn@google.com>
Reviewed-by: Jonas Termansen <sortie@google.com>
This commit is contained in:
Leaf Petersen 2020-06-15 19:41:46 +00:00 committed by commit-bot@chromium.org
parent 9a87cf9174
commit d2543e32f4
12 changed files with 131 additions and 2173 deletions

View file

@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a // 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. // BSD-style license that can be found in the LICENSE file.
// @dart = 2.6
library dart._http; library dart._http;
import "dart:async"; import "dart:async";
@ -13,15 +11,19 @@ import "dart:developer";
import "dart:io"; import "dart:io";
import "dart:math"; import "dart:math";
import "dart:typed_data"; import "dart:typed_data";
import "package:expect/expect.dart"; import "package:expect/expect.dart";
part "../../../sdk/lib/_http/crypto.dart"; import "../../../sdk_nnbd/lib/internal/internal.dart"
part "../../../sdk/lib/_http/embedder_config.dart"; show Since, valueOfNonNullableParamWithDefault, HttpStatus;
part "../../../sdk/lib/_http/http_impl.dart";
part "../../../sdk/lib/_http/http_date.dart"; part "../../../sdk_nnbd/lib/_http/crypto.dart";
part "../../../sdk/lib/_http/http_parser.dart"; part "../../../sdk_nnbd/lib/_http/embedder_config.dart";
part "../../../sdk/lib/_http/http_headers.dart"; part "../../../sdk_nnbd/lib/_http/http_impl.dart";
part "../../../sdk/lib/_http/http_session.dart"; part "../../../sdk_nnbd/lib/_http/http_date.dart";
part "../../../sdk_nnbd/lib/_http/http_parser.dart";
part "../../../sdk_nnbd/lib/_http/http_headers.dart";
part "../../../sdk_nnbd/lib/_http/http_session.dart";
void testParseHttpCookieDate() { void testParseHttpCookieDate() {
Expect.throws(() => HttpDate._parseCookieDate("")); Expect.throws(() => HttpDate._parseCookieDate(""));

View file

@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a // 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. // BSD-style license that can be found in the LICENSE file.
// @dart = 2.6
library dart._http; library dart._http;
import "dart:async"; import "dart:async";
@ -14,48 +12,52 @@ import "dart:io";
import "dart:isolate"; import "dart:isolate";
import "dart:math"; import "dart:math";
import "dart:typed_data"; import "dart:typed_data";
import "package:expect/expect.dart"; import "package:expect/expect.dart";
part "../../../sdk/lib/_http/crypto.dart"; import "../../../sdk_nnbd/lib/internal/internal.dart"
part "../../../sdk/lib/_http/embedder_config.dart"; show Since, valueOfNonNullableParamWithDefault, HttpStatus;
part "../../../sdk/lib/_http/http_impl.dart";
part "../../../sdk/lib/_http/http_date.dart"; part "../../../sdk_nnbd/lib/_http/crypto.dart";
part "../../../sdk/lib/_http/http_parser.dart"; part "../../../sdk_nnbd/lib/_http/embedder_config.dart";
part "../../../sdk/lib/_http/http_headers.dart"; part "../../../sdk_nnbd/lib/_http/http_impl.dart";
part "../../../sdk/lib/_http/http_session.dart"; part "../../../sdk_nnbd/lib/_http/http_date.dart";
part "../../../sdk_nnbd/lib/_http/http_parser.dart";
part "../../../sdk_nnbd/lib/_http/http_headers.dart";
part "../../../sdk_nnbd/lib/_http/http_session.dart";
void testMultiValue() { void testMultiValue() {
_HttpHeaders headers = new _HttpHeaders("1.1"); _HttpHeaders headers = new _HttpHeaders("1.1");
Expect.isNull(headers[HttpHeaders.pragmaHeader]); Expect.isNull(headers[HttpHeaders.pragmaHeader]);
headers.add(HttpHeaders.pragmaHeader, "pragma1"); headers.add(HttpHeaders.pragmaHeader, "pragma1");
Expect.equals(1, headers[HttpHeaders.pragmaHeader].length); Expect.equals(1, headers[HttpHeaders.pragmaHeader]!.length);
Expect.equals(1, headers["pragma"].length); Expect.equals(1, headers["pragma"]!.length);
Expect.equals(1, headers["Pragma"].length); Expect.equals(1, headers["Pragma"]!.length);
Expect.equals(1, headers["pragma"].length); Expect.equals(1, headers["pragma"]!.length);
Expect.equals("pragma1", headers.value(HttpHeaders.pragmaHeader)); Expect.equals("pragma1", headers.value(HttpHeaders.pragmaHeader));
headers.add(HttpHeaders.pragmaHeader, "pragma2"); headers.add(HttpHeaders.pragmaHeader, "pragma2");
Expect.equals(2, headers[HttpHeaders.pragmaHeader].length); Expect.equals(2, headers[HttpHeaders.pragmaHeader]!.length);
Expect.throws( Expect.throws(
() => headers.value(HttpHeaders.pragmaHeader), (e) => e is HttpException); () => headers.value(HttpHeaders.pragmaHeader), (e) => e is HttpException);
headers.add(HttpHeaders.pragmaHeader, ["pragma3", "pragma4"]); headers.add(HttpHeaders.pragmaHeader, ["pragma3", "pragma4"]);
Expect.listEquals(["pragma1", "pragma2", "pragma3", "pragma4"], Expect.listEquals(["pragma1", "pragma2", "pragma3", "pragma4"],
headers[HttpHeaders.pragmaHeader]); headers[HttpHeaders.pragmaHeader]!);
headers.remove(HttpHeaders.pragmaHeader, "pragma3"); headers.remove(HttpHeaders.pragmaHeader, "pragma3");
Expect.equals(3, headers[HttpHeaders.pragmaHeader].length); Expect.equals(3, headers[HttpHeaders.pragmaHeader]!.length);
Expect.listEquals( Expect.listEquals(
["pragma1", "pragma2", "pragma4"], headers[HttpHeaders.pragmaHeader]); ["pragma1", "pragma2", "pragma4"], headers[HttpHeaders.pragmaHeader]!);
headers.remove(HttpHeaders.pragmaHeader, "pragma3"); headers.remove(HttpHeaders.pragmaHeader, "pragma3");
Expect.equals(3, headers[HttpHeaders.pragmaHeader].length); Expect.equals(3, headers[HttpHeaders.pragmaHeader]!.length);
headers.set(HttpHeaders.pragmaHeader, "pragma5"); headers.set(HttpHeaders.pragmaHeader, "pragma5");
Expect.equals(1, headers[HttpHeaders.pragmaHeader].length); Expect.equals(1, headers[HttpHeaders.pragmaHeader]!.length);
headers.set(HttpHeaders.pragmaHeader, ["pragma6", "pragma7"]); headers.set(HttpHeaders.pragmaHeader, ["pragma6", "pragma7"]);
Expect.equals(2, headers[HttpHeaders.pragmaHeader].length); Expect.equals(2, headers[HttpHeaders.pragmaHeader]!.length);
headers.removeAll(HttpHeaders.pragmaHeader); headers.removeAll(HttpHeaders.pragmaHeader);
Expect.isNull(headers[HttpHeaders.pragmaHeader]); Expect.isNull(headers[HttpHeaders.pragmaHeader]);
@ -72,13 +74,13 @@ void testDate() {
headers.date = date1; headers.date = date1;
Expect.equals(date1, headers.date); Expect.equals(date1, headers.date);
Expect.equals(httpDate1, headers.value(HttpHeaders.dateHeader)); Expect.equals(httpDate1, headers.value(HttpHeaders.dateHeader));
Expect.equals(1, headers[HttpHeaders.dateHeader].length); Expect.equals(1, headers[HttpHeaders.dateHeader]!.length);
headers.add(HttpHeaders.dateHeader, httpDate2); headers.add(HttpHeaders.dateHeader, httpDate2);
Expect.equals(1, headers[HttpHeaders.dateHeader].length); Expect.equals(1, headers[HttpHeaders.dateHeader]!.length);
Expect.equals(date2, headers.date); Expect.equals(date2, headers.date);
Expect.equals(httpDate2, headers.value(HttpHeaders.dateHeader)); Expect.equals(httpDate2, headers.value(HttpHeaders.dateHeader));
headers.set(HttpHeaders.dateHeader, httpDate1); headers.set(HttpHeaders.dateHeader, httpDate1);
Expect.equals(1, headers[HttpHeaders.dateHeader].length); Expect.equals(1, headers[HttpHeaders.dateHeader]!.length);
Expect.equals(date1, headers.date); Expect.equals(date1, headers.date);
Expect.equals(httpDate1, headers.value(HttpHeaders.dateHeader)); Expect.equals(httpDate1, headers.value(HttpHeaders.dateHeader));
@ -98,13 +100,13 @@ void testExpires() {
headers.expires = date1; headers.expires = date1;
Expect.equals(date1, headers.expires); Expect.equals(date1, headers.expires);
Expect.equals(httpDate1, headers.value(HttpHeaders.expiresHeader)); Expect.equals(httpDate1, headers.value(HttpHeaders.expiresHeader));
Expect.equals(1, headers[HttpHeaders.expiresHeader].length); Expect.equals(1, headers[HttpHeaders.expiresHeader]!.length);
headers.add(HttpHeaders.expiresHeader, httpDate2); headers.add(HttpHeaders.expiresHeader, httpDate2);
Expect.equals(1, headers[HttpHeaders.expiresHeader].length); Expect.equals(1, headers[HttpHeaders.expiresHeader]!.length);
Expect.equals(date2, headers.expires); Expect.equals(date2, headers.expires);
Expect.equals(httpDate2, headers.value(HttpHeaders.expiresHeader)); Expect.equals(httpDate2, headers.value(HttpHeaders.expiresHeader));
headers.set(HttpHeaders.expiresHeader, httpDate1); headers.set(HttpHeaders.expiresHeader, httpDate1);
Expect.equals(1, headers[HttpHeaders.expiresHeader].length); Expect.equals(1, headers[HttpHeaders.expiresHeader]!.length);
Expect.equals(date1, headers.expires); Expect.equals(date1, headers.expires);
Expect.equals(httpDate1, headers.value(HttpHeaders.expiresHeader)); Expect.equals(httpDate1, headers.value(HttpHeaders.expiresHeader));
@ -124,13 +126,13 @@ void testIfModifiedSince() {
headers.ifModifiedSince = date1; headers.ifModifiedSince = date1;
Expect.equals(date1, headers.ifModifiedSince); Expect.equals(date1, headers.ifModifiedSince);
Expect.equals(httpDate1, headers.value(HttpHeaders.ifModifiedSinceHeader)); Expect.equals(httpDate1, headers.value(HttpHeaders.ifModifiedSinceHeader));
Expect.equals(1, headers[HttpHeaders.ifModifiedSinceHeader].length); Expect.equals(1, headers[HttpHeaders.ifModifiedSinceHeader]!.length);
headers.add(HttpHeaders.ifModifiedSinceHeader, httpDate2); headers.add(HttpHeaders.ifModifiedSinceHeader, httpDate2);
Expect.equals(1, headers[HttpHeaders.ifModifiedSinceHeader].length); Expect.equals(1, headers[HttpHeaders.ifModifiedSinceHeader]!.length);
Expect.equals(date2, headers.ifModifiedSince); Expect.equals(date2, headers.ifModifiedSince);
Expect.equals(httpDate2, headers.value(HttpHeaders.ifModifiedSinceHeader)); Expect.equals(httpDate2, headers.value(HttpHeaders.ifModifiedSinceHeader));
headers.set(HttpHeaders.ifModifiedSinceHeader, httpDate1); headers.set(HttpHeaders.ifModifiedSinceHeader, httpDate1);
Expect.equals(1, headers[HttpHeaders.ifModifiedSinceHeader].length); Expect.equals(1, headers[HttpHeaders.ifModifiedSinceHeader]!.length);
Expect.equals(date1, headers.ifModifiedSince); Expect.equals(date1, headers.ifModifiedSince);
Expect.equals(httpDate1, headers.value(HttpHeaders.ifModifiedSinceHeader)); Expect.equals(httpDate1, headers.value(HttpHeaders.ifModifiedSinceHeader));
@ -156,7 +158,7 @@ void testHost() {
Expect.equals(host, headers.host); Expect.equals(host, headers.host);
Expect.equals(HttpClient.defaultHttpPort, headers.port); Expect.equals(HttpClient.defaultHttpPort, headers.port);
headers.add(HttpHeaders.hostHeader, "$host:4567"); headers.add(HttpHeaders.hostHeader, "$host:4567");
Expect.equals(1, headers[HttpHeaders.hostHeader].length); Expect.equals(1, headers[HttpHeaders.hostHeader]!.length);
Expect.equals(host, headers.host); Expect.equals(host, headers.host);
Expect.equals(4567, headers.port); Expect.equals(4567, headers.port);
@ -247,11 +249,11 @@ void testEnumeration() {
void testHeaderValue() { void testHeaderValue() {
void check(HeaderValue headerValue, String value, void check(HeaderValue headerValue, String value,
[Map<String, String> parameters]) { [Map<String, String?>? parameters]) {
Expect.equals(value, headerValue.value); Expect.equals(value, headerValue.value);
if (parameters != null) { if (parameters != null) {
Expect.equals(parameters.length, headerValue.parameters.length); Expect.equals(parameters.length, headerValue.parameters.length);
parameters.forEach((String name, String value) { parameters.forEach((String name, String? value) {
Expect.equals(value, headerValue.parameters[name]); Expect.equals(value, headerValue.parameters[name]);
}); });
} else { } else {
@ -327,13 +329,13 @@ void testHeaderValue() {
void testContentType() { void testContentType() {
void check(ContentType contentType, String primaryType, String subType, void check(ContentType contentType, String primaryType, String subType,
[Map<String, String> parameters]) { [Map<String, String?>? parameters]) {
Expect.equals(primaryType, contentType.primaryType); Expect.equals(primaryType, contentType.primaryType);
Expect.equals(subType, contentType.subType); Expect.equals(subType, contentType.subType);
Expect.equals("$primaryType/$subType", contentType.value); Expect.equals("$primaryType/$subType", contentType.value);
if (parameters != null) { if (parameters != null) {
Expect.equals(parameters.length, contentType.parameters.length); Expect.equals(parameters.length, contentType.parameters.length);
parameters.forEach((String name, String value) { parameters.forEach((String name, String? value) {
Expect.equals(value, contentType.parameters[name]); Expect.equals(value, contentType.parameters[name]);
}); });
} else { } else {
@ -423,13 +425,13 @@ void testKnownContentTypes() {
void testContentTypeCache() { void testContentTypeCache() {
_HttpHeaders headers = new _HttpHeaders("1.1"); _HttpHeaders headers = new _HttpHeaders("1.1");
headers.set(HttpHeaders.contentTypeHeader, "text/html"); headers.set(HttpHeaders.contentTypeHeader, "text/html");
Expect.equals("text", headers.contentType.primaryType); Expect.equals("text", headers.contentType?.primaryType);
Expect.equals("html", headers.contentType.subType); Expect.equals("html", headers.contentType?.subType);
Expect.equals("text/html", headers.contentType.value); Expect.equals("text/html", headers.contentType?.value);
headers.set(HttpHeaders.contentTypeHeader, "text/plain; charset=utf-8"); headers.set(HttpHeaders.contentTypeHeader, "text/plain; charset=utf-8");
Expect.equals("text", headers.contentType.primaryType); Expect.equals("text", headers.contentType?.primaryType);
Expect.equals("plain", headers.contentType.subType); Expect.equals("plain", headers.contentType?.subType);
Expect.equals("text/plain", headers.contentType.value); Expect.equals("text/plain", headers.contentType?.value);
headers.removeAll(HttpHeaders.contentTypeHeader); headers.removeAll(HttpHeaders.contentTypeHeader);
Expect.isNull(headers.contentType); Expect.isNull(headers.contentType);
} }
@ -626,10 +628,10 @@ void testFolding() {
void testLowercaseAdd() { void testLowercaseAdd() {
_HttpHeaders headers = new _HttpHeaders("1.1"); _HttpHeaders headers = new _HttpHeaders("1.1");
headers.add('A', 'a'); headers.add('A', 'a');
Expect.equals(headers['a'][0], headers['A'][0]); Expect.equals(headers['a']![0], headers['A']![0]);
Expect.equals(headers['A'][0], 'a'); Expect.equals(headers['A']![0], 'a');
headers.add('Foo', 'Foo', preserveHeaderCase: true); headers.add('Foo', 'Foo', preserveHeaderCase: true);
Expect.equals(headers['Foo'][0], 'Foo'); Expect.equals(headers['Foo']![0], 'Foo');
// Header field is Foo. // Header field is Foo.
Expect.isTrue(headers.toString().contains('Foo:')); Expect.isTrue(headers.toString().contains('Foo:'));
@ -650,14 +652,14 @@ void testLowercaseSet() {
// 'Test' should override 'test' entity // 'Test' should override 'test' entity
headers.set('TEST', 'upper cases', preserveHeaderCase: true); headers.set('TEST', 'upper cases', preserveHeaderCase: true);
Expect.isTrue(headers.toString().contains('TEST: upper cases')); Expect.isTrue(headers.toString().contains('TEST: upper cases'));
Expect.equals(1, headers['test'].length); Expect.equals(1, headers['test']!.length);
Expect.equals(headers['test'][0], 'upper cases'); Expect.equals(headers['test']![0], 'upper cases');
// Latest header will be stored. // Latest header will be stored.
headers.set('Test', 'mixed cases', preserveHeaderCase: true); headers.set('Test', 'mixed cases', preserveHeaderCase: true);
Expect.isTrue(headers.toString().contains('Test: mixed cases')); Expect.isTrue(headers.toString().contains('Test: mixed cases'));
Expect.equals(1, headers['test'].length); Expect.equals(1, headers['test']!.length);
Expect.equals(headers['test'][0], 'mixed cases'); Expect.equals(headers['test']![0], 'mixed cases');
} }
void testForEach() { void testForEach() {

View file

@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a // 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. // BSD-style license that can be found in the LICENSE file.
// @dart = 2.6
library dart._http; library dart._http;
import "dart:async"; import "dart:async";
@ -14,15 +12,19 @@ import "dart:io";
import "dart:isolate"; import "dart:isolate";
import "dart:math"; import "dart:math";
import "dart:typed_data"; import "dart:typed_data";
import "package:expect/expect.dart"; import "package:expect/expect.dart";
part "../../../sdk/lib/_http/crypto.dart"; import "../../../sdk_nnbd/lib/internal/internal.dart"
part "../../../sdk/lib/_http/embedder_config.dart"; show Since, valueOfNonNullableParamWithDefault, HttpStatus;
part "../../../sdk/lib/_http/http_impl.dart";
part "../../../sdk/lib/_http/http_date.dart"; part "../../../sdk_nnbd/lib/_http/crypto.dart";
part "../../../sdk/lib/_http/http_parser.dart"; part "../../../sdk_nnbd/lib/_http/embedder_config.dart";
part "../../../sdk/lib/_http/http_headers.dart"; part "../../../sdk_nnbd/lib/_http/http_impl.dart";
part "../../../sdk/lib/_http/http_session.dart"; part "../../../sdk_nnbd/lib/_http/http_date.dart";
part "../../../sdk_nnbd/lib/_http/http_parser.dart";
part "../../../sdk_nnbd/lib/_http/http_headers.dart";
part "../../../sdk_nnbd/lib/_http/http_session.dart";
class HttpParserTest { class HttpParserTest {
static void runAllTests() { static void runAllTests() {
@ -36,26 +38,25 @@ class HttpParserTest {
String request, String expectedMethod, String expectedUri, String request, String expectedMethod, String expectedUri,
{int expectedTransferLength: 0, {int expectedTransferLength: 0,
int expectedBytesReceived: 0, int expectedBytesReceived: 0,
Map<String, String> expectedHeaders: null, Map<String, String>? expectedHeaders: null,
bool chunked: false, bool chunked: false,
bool upgrade: false, bool upgrade: false,
int unparsedLength: 0, int unparsedLength: 0,
bool connectionClose: false, bool connectionClose: false,
String expectedVersion: "1.1"}) { String expectedVersion: "1.1"}) {
StreamController<Uint8List> controller; late StreamController<Uint8List> controller;
void reset() { void reset() {
_HttpParser httpParser = new _HttpParser.requestParser(); _HttpParser httpParser = new _HttpParser.requestParser();
controller = new StreamController(sync: true); controller = new StreamController(sync: true);
var port1 = new ReceivePort(); var port1 = new ReceivePort();
var port2 = new ReceivePort(); var port2 = new ReceivePort();
String method; String? method = null;
Uri uri; Uri? uri = null;
_HttpHeaders headers; _HttpHeaders? headers = null;
int contentLength; int bytesReceived = 0;
int bytesReceived; int unparsedBytesReceived = 0;
int unparsedBytesReceived; bool upgraded = false;
bool upgraded;
httpParser.listenToStream(controller.stream); httpParser.listenToStream(controller.stream);
var subscription = httpParser.listen((incoming) { var subscription = httpParser.listen((incoming) {
@ -72,7 +73,7 @@ class HttpParserTest {
} }
if (expectedHeaders != null) { if (expectedHeaders != null) {
expectedHeaders.forEach((String name, String value) => expectedHeaders.forEach((String name, String value) =>
Expect.equals(value, headers[name][0])); Expect.equals(value, headers![name]![0]));
} }
incoming.listen((List<int> data) { incoming.listen((List<int> data) {
Expect.isFalse(upgraded); Expect.isFalse(upgraded);
@ -81,7 +82,7 @@ class HttpParserTest {
port2.close(); port2.close();
Expect.equals(expectedMethod, method); Expect.equals(expectedMethod, method);
Expect.stringEquals(expectedUri, uri.toString()); Expect.stringEquals(expectedUri, uri.toString());
Expect.equals(expectedVersion, headers.protocolVersion); Expect.equals(expectedVersion, headers!.protocolVersion);
if (upgrade) { if (upgrade) {
Expect.equals(0, bytesReceived); Expect.equals(0, bytesReceived);
// port1 is closed by the listener on the detached data. // port1 is closed by the listener on the detached data.
@ -104,13 +105,6 @@ class HttpParserTest {
port1.close(); port1.close();
}); });
}); });
method = null;
uri = null;
headers = null;
bytesReceived = 0;
unparsedBytesReceived = 0;
upgraded = false;
} }
void testWrite(List<int> requestData, [int chunkSize = -1]) { void testWrite(List<int> requestData, [int chunkSize = -1]) {
@ -118,7 +112,7 @@ class HttpParserTest {
reset(); reset();
for (int pos = 0; pos < requestData.length; pos += chunkSize) { for (int pos = 0; pos < requestData.length; pos += chunkSize) {
int end = min(requestData.length, pos + chunkSize); int end = min(requestData.length, pos + chunkSize);
controller.add(requestData.sublist(pos, end)); controller.add(requestData.sublist(pos, end) as Uint8List);
} }
controller.close(); controller.close();
} }
@ -135,7 +129,7 @@ class HttpParserTest {
String request, String expectedMethod, String expectedUri, String request, String expectedMethod, String expectedUri,
{int expectedTransferLength: 0, {int expectedTransferLength: 0,
int expectedBytesReceived: 0, int expectedBytesReceived: 0,
Map<String, String> expectedHeaders: null, Map<String, String>? expectedHeaders: null,
bool chunked: false, bool chunked: false,
bool upgrade: false, bool upgrade: false,
int unparsedLength: 0, int unparsedLength: 0,
@ -164,8 +158,8 @@ class HttpParserTest {
static void _testParseInvalidRequest(String request) { static void _testParseInvalidRequest(String request) {
_HttpParser httpParser; _HttpParser httpParser;
bool errorCalled; bool errorCalled = false;
StreamController<Uint8List> controller; late StreamController<Uint8List> controller;
void reset() { void reset() {
httpParser = new _HttpParser.requestParser(); httpParser = new _HttpParser.requestParser();
@ -192,7 +186,7 @@ class HttpParserTest {
pos < requestData.length && !errorCalled; pos < requestData.length && !errorCalled;
pos += chunkSize) { pos += chunkSize) {
int end = min(requestData.length, pos + chunkSize); int end = min(requestData.length, pos + chunkSize);
controller.add(requestData.sublist(pos, end)); controller.add(requestData.sublist(pos, end) as Uint8List);
} }
controller.close(); controller.close();
} }
@ -209,27 +203,27 @@ class HttpParserTest {
String response, int expectedStatusCode, String expectedReasonPhrase, String response, int expectedStatusCode, String expectedReasonPhrase,
{int expectedTransferLength: 0, {int expectedTransferLength: 0,
int expectedBytesReceived: 0, int expectedBytesReceived: 0,
Map<String, String> expectedHeaders: null, Map<String, String>? expectedHeaders: null,
bool chunked: false, bool chunked: false,
bool close: false, bool close: false,
String responseToMethod: null, String? responseToMethod: null,
bool connectionClose: false, bool connectionClose: false,
bool upgrade: false, bool upgrade: false,
int unparsedLength: 0, int unparsedLength: 0,
String expectedVersion: "1.1"}) { String expectedVersion: "1.1"}) {
StreamController<Uint8List> controller; late StreamController<Uint8List> controller;
bool upgraded; bool upgraded;
void reset() { void reset() {
_HttpParser httpParser; _HttpParser httpParser;
bool headersCompleteCalled; bool headersCompleteCalled = false;
bool dataEndCalled; bool dataEndCalled = false;
bool dataEndClose; bool? dataEndClose = null;
int statusCode; int statusCode = -1;
String reasonPhrase; String? reasonPhrase = null;
_HttpHeaders headers; _HttpHeaders? headers = null;
int contentLength; int bytesReceived = 0;
int bytesReceived;
httpParser = new _HttpParser.responseParser(); httpParser = new _HttpParser.responseParser();
controller = new StreamController(sync: true); controller = new StreamController(sync: true);
var port = new ReceivePort(); var port = new ReceivePort();
@ -240,7 +234,7 @@ class HttpParserTest {
void whenDone() { void whenDone() {
doneCallCount++; doneCallCount++;
if (doneCallCount < 2) return; if (doneCallCount < 2) return;
Expect.equals(expectedVersion, headers.protocolVersion); Expect.equals(expectedVersion, headers!.protocolVersion);
Expect.equals(expectedStatusCode, statusCode); Expect.equals(expectedStatusCode, statusCode);
Expect.equals(expectedReasonPhrase, reasonPhrase); Expect.equals(expectedReasonPhrase, reasonPhrase);
Expect.isTrue(headersCompleteCalled); Expect.isTrue(headersCompleteCalled);
@ -254,7 +248,7 @@ class HttpParserTest {
var subscription = httpParser.listen((incoming) { var subscription = httpParser.listen((incoming) {
port.close(); port.close();
statusCode = incoming.statusCode; statusCode = incoming.statusCode!;
reasonPhrase = incoming.reasonPhrase; reasonPhrase = incoming.reasonPhrase;
headers = incoming.headers; headers = incoming.headers;
Expect.isFalse(headersCompleteCalled); Expect.isFalse(headersCompleteCalled);
@ -265,7 +259,7 @@ class HttpParserTest {
} }
if (expectedHeaders != null) { if (expectedHeaders != null) {
expectedHeaders.forEach((String name, String value) { expectedHeaders.forEach((String name, String value) {
Expect.equals(value, headers[name][0]); Expect.equals(value, headers![name]![0]);
}); });
} }
Expect.equals(upgrade, httpParser.upgrade); Expect.equals(upgrade, httpParser.upgrade);
@ -279,14 +273,6 @@ class HttpParserTest {
whenDone(); whenDone();
}); });
}, onDone: whenDone); }, onDone: whenDone);
headersCompleteCalled = false;
dataEndCalled = false;
dataEndClose = null;
statusCode = -1;
reasonPhrase = null;
headers = null;
bytesReceived = 0;
} }
void testWrite(List<int> requestData, [int chunkSize = -1]) { void testWrite(List<int> requestData, [int chunkSize = -1]) {
@ -294,7 +280,7 @@ class HttpParserTest {
reset(); reset();
for (int pos = 0; pos < requestData.length; pos += chunkSize) { for (int pos = 0; pos < requestData.length; pos += chunkSize) {
int end = min(requestData.length, pos + chunkSize); int end = min(requestData.length, pos + chunkSize);
controller.add(requestData.sublist(pos, end)); controller.add(requestData.sublist(pos, end) as Uint8List);
} }
if (close) controller.close(); if (close) controller.close();
} }
@ -337,7 +323,7 @@ class HttpParserTest {
pos < requestData.length && !errorCalled; pos < requestData.length && !errorCalled;
pos += chunkSize) { pos += chunkSize) {
int end = min(requestData.length, pos + chunkSize); int end = min(requestData.length, pos + chunkSize);
controller.add(requestData.sublist(pos, end)); controller.add(requestData.sublist(pos, end) as Uint8List);
} }
controller.close(); controller.close();
} }

View file

@ -9,8 +9,6 @@
// OtherResources=certificates/server_chain.pem // OtherResources=certificates/server_chain.pem
// OtherResources=certificates/server_key.pem // OtherResources=certificates/server_key.pem
// @dart = 2.6
library dart._http; library dart._http;
import "dart:async"; import "dart:async";
@ -20,9 +18,8 @@ import "dart:typed_data";
import "package:async_helper/async_helper.dart"; import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart"; import "package:expect/expect.dart";
import "package:path/path.dart";
part "../../../sdk/lib/_http/crypto.dart"; part "../../../sdk_nnbd/lib/_http/crypto.dart";
const String webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; const String webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
const String CERT_NAME = 'localhost_cert'; const String CERT_NAME = 'localhost_cert';
@ -44,7 +41,7 @@ SecurityContext clientContext = new SecurityContext()
class SecurityConfiguration { class SecurityConfiguration {
final bool secure; final bool secure;
SecurityConfiguration({bool this.secure}); SecurityConfiguration({required bool this.secure});
Future<HttpServer> createServer({int backlog: 0}) => secure Future<HttpServer> createServer({int backlog: 0}) => secure
? HttpServer.bindSecure(HOST_NAME, 0, serverContext, backlog: backlog) ? HttpServer.bindSecure(HOST_NAME, 0, serverContext, backlog: backlog)
@ -61,7 +58,7 @@ class SecurityConfiguration {
response.statusCode = HttpStatus.switchingProtocols; response.statusCode = HttpStatus.switchingProtocols;
response.headers.set(HttpHeaders.connectionHeader, "upgrade"); response.headers.set(HttpHeaders.connectionHeader, "upgrade");
response.headers.set(HttpHeaders.upgradeHeader, "websocket"); response.headers.set(HttpHeaders.upgradeHeader, "websocket");
String key = request.headers.value("Sec-WebSocket-Key"); String? key = request.headers.value("Sec-WebSocket-Key");
_SHA1 sha1 = new _SHA1(); _SHA1 sha1 = new _SHA1();
sha1.add("$key$webSocketGUID".codeUnits); sha1.add("$key$webSocketGUID".codeUnits);
String accept = _CryptoUtils.bytesToBase64(sha1.close()); String accept = _CryptoUtils.bytesToBase64(sha1.close());

View file

@ -7,17 +7,16 @@
// VMOptions=--short_socket_write // VMOptions=--short_socket_write
// VMOptions=--short_socket_read --short_socket_write // VMOptions=--short_socket_read --short_socket_write
// @dart = 2.6
library dart._http; library dart._http;
import "package:expect/expect.dart";
import "dart:async"; import "dart:async";
import "dart:io"; import "dart:io";
import "dart:math"; import "dart:math";
import "dart:typed_data"; import "dart:typed_data";
part "../../../sdk/lib/_http/crypto.dart"; import "package:expect/expect.dart";
part "../../../sdk_nnbd/lib/_http/crypto.dart";
const String webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; const String webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
@ -29,7 +28,7 @@ void testPing(int totalConnections) {
response.statusCode = HttpStatus.switchingProtocols; response.statusCode = HttpStatus.switchingProtocols;
response.headers.set(HttpHeaders.connectionHeader, "upgrade"); response.headers.set(HttpHeaders.connectionHeader, "upgrade");
response.headers.set(HttpHeaders.upgradeHeader, "websocket"); response.headers.set(HttpHeaders.upgradeHeader, "websocket");
String key = request.headers.value("Sec-WebSocket-Key"); String? key = request.headers.value("Sec-WebSocket-Key");
_SHA1 sha1 = new _SHA1(); _SHA1 sha1 = new _SHA1();
sha1.add("$key$webSocketGUID".codeUnits); sha1.add("$key$webSocketGUID".codeUnits);
String accept = _CryptoUtils.bytesToBase64(sha1.close()); String accept = _CryptoUtils.bytesToBase64(sha1.close());

View file

@ -2,12 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a // 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. // BSD-style license that can be found in the LICENSE file.
// @dart = 2.6
library dart._http; library dart._http;
import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";
import "dart:async"; import "dart:async";
import "dart:collection"; import "dart:collection";
import "dart:convert"; import "dart:convert";
@ -17,15 +13,21 @@ import "dart:math";
import "dart:typed_data"; import "dart:typed_data";
import "dart:isolate"; import "dart:isolate";
part "../../../sdk/lib/_http/crypto.dart"; import "package:async_helper/async_helper.dart";
part "../../../sdk/lib/_http/embedder_config.dart"; import "package:expect/expect.dart";
part "../../../sdk/lib/_http/http_impl.dart";
part "../../../sdk/lib/_http/http_date.dart"; import "../../../sdk_nnbd/lib/internal/internal.dart"
part "../../../sdk/lib/_http/http_parser.dart"; show Since, valueOfNonNullableParamWithDefault, HttpStatus;
part "../../../sdk/lib/_http/http_headers.dart";
part "../../../sdk/lib/_http/http_session.dart"; part "../../../sdk_nnbd/lib/_http/crypto.dart";
part "../../../sdk/lib/_http/websocket.dart"; part "../../../sdk_nnbd/lib/_http/embedder_config.dart";
part "../../../sdk/lib/_http/websocket_impl.dart"; part "../../../sdk_nnbd/lib/_http/http_impl.dart";
part "../../../sdk_nnbd/lib/_http/http_date.dart";
part "../../../sdk_nnbd/lib/_http/http_parser.dart";
part "../../../sdk_nnbd/lib/_http/http_headers.dart";
part "../../../sdk_nnbd/lib/_http/http_session.dart";
part "../../../sdk_nnbd/lib/_http/websocket.dart";
part "../../../sdk_nnbd/lib/_http/websocket_impl.dart";
class WebSocketFrame { class WebSocketFrame {
WebSocketFrame(int opcode, List<int> data); WebSocketFrame(int opcode, List<int> data);
@ -35,16 +37,16 @@ class WebSocketFrame {
// collect the message and expect it to be equal to the // collect the message and expect it to be equal to the
// expectedMessage field when fully received. // expectedMessage field when fully received.
class WebSocketMessageCollector { class WebSocketMessageCollector {
List<int> expectedMessage; List<int>? expectedMessage;
int messageCount = 0; int messageCount = 0;
var data; var data;
Function onClosed; void Function()? onClosed;
WebSocketMessageCollector(Stream stream, WebSocketMessageCollector(Stream stream,
[List<int> this.expectedMessage = null]) { [List<int>? this.expectedMessage = null]) {
stream.listen(onMessageData, onDone: onClosed, onError: onError); stream.listen(onMessageData, onDone: onClosed, onError: onError);
} }
@ -52,7 +54,7 @@ class WebSocketMessageCollector {
if (buffer is String) { if (buffer is String) {
buffer = utf8.encode(buffer); buffer = utf8.encode(buffer);
} }
Expect.listEquals(expectedMessage, buffer); Expect.listEquals(expectedMessage!, buffer);
messageCount++; messageCount++;
data = buffer; data = buffer;
} }
@ -69,7 +71,7 @@ const int FRAME_OPCODE_TEXT = 1;
const int FRAME_OPCODE_BINARY = 2; const int FRAME_OPCODE_BINARY = 2;
// Function for building a web socket frame. // Function for building a web socket frame.
List<int> createFrame(bool fin, int opcode, int maskingKey, List<int> data, List<int> createFrame(bool fin, int opcode, int? maskingKey, List<int> data,
int offset, int count) { int offset, int count) {
int frameSize = 2; int frameSize = 2;
if (count > 125) frameSize += 2; if (count > 125) frameSize += 2;
@ -145,8 +147,7 @@ void testFullMessages() {
void runTest(int from, int to, int step) { void runTest(int from, int to, int step) {
for (int messageLength = from; messageLength < to; messageLength += step) { for (int messageLength = from; messageLength < to; messageLength += step) {
List<int> message = new List<int>(messageLength); List<int> message = [for (int i = 0; i < messageLength; i++) i & 0x7F];
for (int i = 0; i < messageLength; i++) message[i] = i & 0x7F;
testMessage(FRAME_OPCODE_TEXT, message); testMessage(FRAME_OPCODE_TEXT, message);
for (int i = 0; i < messageLength; i++) message[i] = i & 0xFF; for (int i = 0; i < messageLength; i++) message[i] = i & 0xFF;
testMessage(FRAME_OPCODE_BINARY, message); testMessage(FRAME_OPCODE_BINARY, message);
@ -206,8 +207,7 @@ void testFragmentedMessages() {
void runTest(int from, int to, int step) { void runTest(int from, int to, int step) {
for (int messageLength = from; messageLength < to; messageLength += step) { for (int messageLength = from; messageLength < to; messageLength += step) {
List<int> message = new List<int>(messageLength); List<int> message = [for (int i = 0; i < messageLength; i++) i & 0x7F];
for (int i = 0; i < messageLength; i++) message[i] = i & 0x7F;
testMessageFragmentation(FRAME_OPCODE_TEXT, message); testMessageFragmentation(FRAME_OPCODE_TEXT, message);
for (int i = 0; i < messageLength; i++) message[i] = i & 0xFF; for (int i = 0; i < messageLength; i++) message[i] = i & 0xFF;
testMessageFragmentation(FRAME_OPCODE_BINARY, message); testMessageFragmentation(FRAME_OPCODE_BINARY, message);

View file

@ -1,45 +0,0 @@
// Copyright (c) 2012, 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.
// @dart = 2.6
library dart._http;
import "dart:async";
import "dart:collection";
import "dart:convert";
import "dart:developer";
import "dart:io";
import "dart:math";
import "dart:typed_data";
import "package:expect/expect.dart";
part "../../../sdk/lib/_http/crypto.dart";
part "../../../sdk/lib/_http/embedder_config.dart";
part "../../../sdk/lib/_http/http_impl.dart";
part "../../../sdk/lib/_http/http_date.dart";
part "../../../sdk/lib/_http/http_parser.dart";
part "../../../sdk/lib/_http/http_headers.dart";
part "../../../sdk/lib/_http/http_session.dart";
void testParseHttpCookieDate() {
Expect.throws(() => HttpDate._parseCookieDate(""));
test(int year, int month, int day, int hours, int minutes, int seconds,
String formatted) {
DateTime date =
new DateTime.utc(year, month, day, hours, minutes, seconds, 0);
Expect.equals(date, HttpDate._parseCookieDate(formatted));
}
test(2012, DateTime.june, 19, 14, 15, 01, "tue, 19-jun-12 14:15:01 gmt");
test(2021, DateTime.june, 09, 10, 18, 14, "Wed, 09-Jun-2021 10:18:14 GMT");
test(2021, DateTime.january, 13, 22, 23, 01, "Wed, 13-Jan-2021 22:23:01 GMT");
test(2013, DateTime.january, 15, 21, 47, 38, "Tue, 15-Jan-2013 21:47:38 GMT");
test(1970, DateTime.january, 01, 00, 00, 01, "Thu, 01-Jan-1970 00:00:01 GMT");
}
void main() {
testParseHttpCookieDate();
}

View file

@ -1,726 +0,0 @@
// 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.
// @dart = 2.6
library dart._http;
import "dart:async";
import "dart:collection";
import "dart:convert";
import "dart:developer";
import "dart:io";
import "dart:isolate";
import "dart:math";
import "dart:typed_data";
import "package:expect/expect.dart";
part "../../../sdk/lib/_http/crypto.dart";
part "../../../sdk/lib/_http/embedder_config.dart";
part "../../../sdk/lib/_http/http_impl.dart";
part "../../../sdk/lib/_http/http_date.dart";
part "../../../sdk/lib/_http/http_parser.dart";
part "../../../sdk/lib/_http/http_headers.dart";
part "../../../sdk/lib/_http/http_session.dart";
void testMultiValue() {
_HttpHeaders headers = new _HttpHeaders("1.1");
Expect.isNull(headers[HttpHeaders.pragmaHeader]);
headers.add(HttpHeaders.pragmaHeader, "pragma1");
Expect.equals(1, headers[HttpHeaders.pragmaHeader].length);
Expect.equals(1, headers["pragma"].length);
Expect.equals(1, headers["Pragma"].length);
Expect.equals(1, headers["pragma"].length);
Expect.equals("pragma1", headers.value(HttpHeaders.pragmaHeader));
headers.add(HttpHeaders.pragmaHeader, "pragma2");
Expect.equals(2, headers[HttpHeaders.pragmaHeader].length);
Expect.throws(
() => headers.value(HttpHeaders.pragmaHeader), (e) => e is HttpException);
headers.add(HttpHeaders.pragmaHeader, ["pragma3", "pragma4"]);
Expect.listEquals(["pragma1", "pragma2", "pragma3", "pragma4"],
headers[HttpHeaders.pragmaHeader]);
headers.remove(HttpHeaders.pragmaHeader, "pragma3");
Expect.equals(3, headers[HttpHeaders.pragmaHeader].length);
Expect.listEquals(
["pragma1", "pragma2", "pragma4"], headers[HttpHeaders.pragmaHeader]);
headers.remove(HttpHeaders.pragmaHeader, "pragma3");
Expect.equals(3, headers[HttpHeaders.pragmaHeader].length);
headers.set(HttpHeaders.pragmaHeader, "pragma5");
Expect.equals(1, headers[HttpHeaders.pragmaHeader].length);
headers.set(HttpHeaders.pragmaHeader, ["pragma6", "pragma7"]);
Expect.equals(2, headers[HttpHeaders.pragmaHeader].length);
headers.removeAll(HttpHeaders.pragmaHeader);
Expect.isNull(headers[HttpHeaders.pragmaHeader]);
}
void testDate() {
DateTime date1 = new DateTime.utc(1999, DateTime.june, 11, 18, 46, 53, 0);
String httpDate1 = "Fri, 11 Jun 1999 18:46:53 GMT";
DateTime date2 = new DateTime.utc(2000, DateTime.august, 16, 12, 34, 56, 0);
String httpDate2 = "Wed, 16 Aug 2000 12:34:56 GMT";
_HttpHeaders headers = new _HttpHeaders("1.1");
Expect.isNull(headers.date);
headers.date = date1;
Expect.equals(date1, headers.date);
Expect.equals(httpDate1, headers.value(HttpHeaders.dateHeader));
Expect.equals(1, headers[HttpHeaders.dateHeader].length);
headers.add(HttpHeaders.dateHeader, httpDate2);
Expect.equals(1, headers[HttpHeaders.dateHeader].length);
Expect.equals(date2, headers.date);
Expect.equals(httpDate2, headers.value(HttpHeaders.dateHeader));
headers.set(HttpHeaders.dateHeader, httpDate1);
Expect.equals(1, headers[HttpHeaders.dateHeader].length);
Expect.equals(date1, headers.date);
Expect.equals(httpDate1, headers.value(HttpHeaders.dateHeader));
headers.set(HttpHeaders.dateHeader, "xxx");
Expect.equals("xxx", headers.value(HttpHeaders.dateHeader));
Expect.equals(null, headers.date);
}
void testExpires() {
DateTime date1 = new DateTime.utc(1999, DateTime.june, 11, 18, 46, 53, 0);
String httpDate1 = "Fri, 11 Jun 1999 18:46:53 GMT";
DateTime date2 = new DateTime.utc(2000, DateTime.august, 16, 12, 34, 56, 0);
String httpDate2 = "Wed, 16 Aug 2000 12:34:56 GMT";
_HttpHeaders headers = new _HttpHeaders("1.1");
Expect.isNull(headers.expires);
headers.expires = date1;
Expect.equals(date1, headers.expires);
Expect.equals(httpDate1, headers.value(HttpHeaders.expiresHeader));
Expect.equals(1, headers[HttpHeaders.expiresHeader].length);
headers.add(HttpHeaders.expiresHeader, httpDate2);
Expect.equals(1, headers[HttpHeaders.expiresHeader].length);
Expect.equals(date2, headers.expires);
Expect.equals(httpDate2, headers.value(HttpHeaders.expiresHeader));
headers.set(HttpHeaders.expiresHeader, httpDate1);
Expect.equals(1, headers[HttpHeaders.expiresHeader].length);
Expect.equals(date1, headers.expires);
Expect.equals(httpDate1, headers.value(HttpHeaders.expiresHeader));
headers.set(HttpHeaders.expiresHeader, "xxx");
Expect.equals("xxx", headers.value(HttpHeaders.expiresHeader));
Expect.equals(null, headers.expires);
}
void testIfModifiedSince() {
DateTime date1 = new DateTime.utc(1999, DateTime.june, 11, 18, 46, 53, 0);
String httpDate1 = "Fri, 11 Jun 1999 18:46:53 GMT";
DateTime date2 = new DateTime.utc(2000, DateTime.august, 16, 12, 34, 56, 0);
String httpDate2 = "Wed, 16 Aug 2000 12:34:56 GMT";
_HttpHeaders headers = new _HttpHeaders("1.1");
Expect.isNull(headers.ifModifiedSince);
headers.ifModifiedSince = date1;
Expect.equals(date1, headers.ifModifiedSince);
Expect.equals(httpDate1, headers.value(HttpHeaders.ifModifiedSinceHeader));
Expect.equals(1, headers[HttpHeaders.ifModifiedSinceHeader].length);
headers.add(HttpHeaders.ifModifiedSinceHeader, httpDate2);
Expect.equals(1, headers[HttpHeaders.ifModifiedSinceHeader].length);
Expect.equals(date2, headers.ifModifiedSince);
Expect.equals(httpDate2, headers.value(HttpHeaders.ifModifiedSinceHeader));
headers.set(HttpHeaders.ifModifiedSinceHeader, httpDate1);
Expect.equals(1, headers[HttpHeaders.ifModifiedSinceHeader].length);
Expect.equals(date1, headers.ifModifiedSince);
Expect.equals(httpDate1, headers.value(HttpHeaders.ifModifiedSinceHeader));
headers.set(HttpHeaders.ifModifiedSinceHeader, "xxx");
Expect.equals("xxx", headers.value(HttpHeaders.ifModifiedSinceHeader));
Expect.equals(null, headers.ifModifiedSince);
}
void testHost() {
String host = "www.google.com";
_HttpHeaders headers = new _HttpHeaders("1.1");
Expect.isNull(headers.host);
Expect.isNull(headers.port);
headers.host = host;
Expect.equals(host, headers.value(HttpHeaders.hostHeader));
headers.port = 1234;
Expect.equals("$host:1234", headers.value(HttpHeaders.hostHeader));
headers.port = HttpClient.defaultHttpPort;
Expect.equals(host, headers.value(HttpHeaders.hostHeader));
headers = new _HttpHeaders("1.1");
headers.add(HttpHeaders.hostHeader, host);
Expect.equals(host, headers.host);
Expect.equals(HttpClient.defaultHttpPort, headers.port);
headers.add(HttpHeaders.hostHeader, "$host:4567");
Expect.equals(1, headers[HttpHeaders.hostHeader].length);
Expect.equals(host, headers.host);
Expect.equals(4567, headers.port);
headers = new _HttpHeaders("1.1");
headers.add(HttpHeaders.hostHeader, "$host:xxx");
Expect.equals("$host:xxx", headers.value(HttpHeaders.hostHeader));
Expect.equals(host, headers.host);
Expect.isNull(headers.port);
headers = new _HttpHeaders("1.1");
headers.add(HttpHeaders.hostHeader, ":1234");
Expect.equals(":1234", headers.value(HttpHeaders.hostHeader));
Expect.isNull(headers.host);
Expect.equals(1234, headers.port);
}
void testTransferEncoding() {
expectChunked(headers) {
Expect.listEquals(headers['transfer-encoding'], ['chunked']);
Expect.isTrue(headers.chunkedTransferEncoding);
}
expectNonChunked(headers) {
Expect.isNull(headers['transfer-encoding']);
Expect.isFalse(headers.chunkedTransferEncoding);
}
_HttpHeaders headers;
headers = new _HttpHeaders("1.1");
headers.chunkedTransferEncoding = true;
expectChunked(headers);
headers.set('transfer-encoding', ['chunked']);
expectChunked(headers);
headers = new _HttpHeaders("1.1");
headers.set('transfer-encoding', ['chunked']);
expectChunked(headers);
headers.chunkedTransferEncoding = true;
expectChunked(headers);
headers = new _HttpHeaders("1.1");
headers.chunkedTransferEncoding = true;
headers.chunkedTransferEncoding = false;
expectNonChunked(headers);
headers = new _HttpHeaders("1.1");
headers.chunkedTransferEncoding = true;
headers.remove('transfer-encoding', 'chunked');
expectNonChunked(headers);
headers = new _HttpHeaders("1.1");
headers.set('transfer-encoding', ['chunked']);
headers.chunkedTransferEncoding = false;
expectNonChunked(headers);
headers = new _HttpHeaders("1.1");
headers.set('transfer-encoding', ['chunked']);
headers.remove('transfer-encoding', 'chunked');
expectNonChunked(headers);
}
void testEnumeration() {
_HttpHeaders headers = new _HttpHeaders("1.1");
Expect.isNull(headers[HttpHeaders.pragmaHeader]);
headers.add("My-Header-1", "value 1");
headers.add("My-Header-2", "value 2");
headers.add("My-Header-1", "value 3");
bool myHeader1 = false;
bool myHeader2 = false;
int totalValues = 0;
headers.forEach((String name, List<String> values) {
totalValues += values.length;
if (name == "my-header-1") {
myHeader1 = true;
Expect.isTrue(values.indexOf("value 1") != -1);
Expect.isTrue(values.indexOf("value 3") != -1);
}
if (name == "my-header-2") {
myHeader2 = true;
Expect.isTrue(values.indexOf("value 2") != -1);
}
});
Expect.isTrue(myHeader1);
Expect.isTrue(myHeader2);
Expect.equals(3, totalValues);
}
void testHeaderValue() {
void check(HeaderValue headerValue, String value,
[Map<String, String> parameters]) {
Expect.equals(value, headerValue.value);
if (parameters != null) {
Expect.equals(parameters.length, headerValue.parameters.length);
parameters.forEach((String name, String value) {
Expect.equals(value, headerValue.parameters[name]);
});
} else {
Expect.equals(0, headerValue.parameters.length);
}
}
HeaderValue headerValue;
headerValue = HeaderValue.parse("");
check(headerValue, "", {});
headerValue = HeaderValue.parse(";");
check(headerValue, "", {});
headerValue = HeaderValue.parse(";;");
check(headerValue, "", {});
headerValue = HeaderValue.parse("v;a");
check(headerValue, "v", {"a": null});
headerValue = HeaderValue.parse("v;a=");
check(headerValue, "v", {"a": ""});
Expect.throws(() => HeaderValue.parse("v;a=\""), (e) => e is HttpException);
headerValue = HeaderValue.parse("v;a=\"\"");
check(headerValue, "v", {"a": ""});
Expect.throws(() => HeaderValue.parse("v;a=\"\\"), (e) => e is HttpException);
Expect.throws(
() => HeaderValue.parse("v;a=\";b=\"c\""), (e) => e is HttpException);
Expect.throws(() => HeaderValue.parse("v;a=b c"), (e) => e is HttpException);
headerValue = HeaderValue.parse("æ;ø=å");
check(headerValue, "æ", {"ø": "å"});
headerValue =
HeaderValue.parse("xxx; aaa=bbb; ccc=\"\\\";\\a\"; ddd=\" \"");
check(headerValue, "xxx", {"aaa": "bbb", "ccc": '\";a', "ddd": " "});
headerValue =
new HeaderValue("xxx", {"aaa": "bbb", "ccc": '\";a', "ddd": " "});
check(headerValue, "xxx", {"aaa": "bbb", "ccc": '\";a', "ddd": " "});
headerValue = HeaderValue.parse("attachment; filename=genome.jpeg;"
"modification-date=\"Wed, 12 February 1997 16:29:51 -0500\"");
var parameters = {
"filename": "genome.jpeg",
"modification-date": "Wed, 12 February 1997 16:29:51 -0500"
};
check(headerValue, "attachment", parameters);
headerValue = new HeaderValue("attachment", parameters);
check(headerValue, "attachment", parameters);
headerValue = HeaderValue.parse(" attachment ;filename=genome.jpeg ;"
"modification-date = \"Wed, 12 February 1997 16:29:51 -0500\"");
check(headerValue, "attachment", parameters);
headerValue = HeaderValue.parse("xxx; aaa; bbb; ccc");
check(headerValue, "xxx", {"aaa": null, "bbb": null, "ccc": null});
headerValue = HeaderValue.parse("v; a=A; b=B, V; c=C", valueSeparator: ";");
check(headerValue, "v", {});
headerValue = HeaderValue.parse("v; a=A; b=B, V; c=C", valueSeparator: ";");
check(headerValue, "v", {});
headerValue = HeaderValue.parse("v; a=A; b=B, V; c=C", valueSeparator: ",");
check(headerValue, "v", {"a": "A", "b": "B"});
Expect.throws(() => HeaderValue.parse("v; a=A; b=B, V; c=C"));
Expect.equals("", HeaderValue().toString());
Expect.equals("", HeaderValue("").toString());
Expect.equals("v", HeaderValue("v").toString());
Expect.equals("v", HeaderValue("v", null).toString());
Expect.equals("v", HeaderValue("v", {}).toString());
Expect.equals("v; ", HeaderValue("v", {"": null}).toString());
Expect.equals("v; a", HeaderValue("v", {"a": null}).toString());
Expect.equals("v; a; b", HeaderValue("v", {"a": null, "b": null}).toString());
Expect.equals(
"v; a; b=c", HeaderValue("v", {"a": null, "b": "c"}).toString());
Expect.equals(
"v; a=c; b", HeaderValue("v", {"a": "c", "b": null}).toString());
Expect.equals("v; a=\"\"", HeaderValue("v", {"a": ""}).toString());
Expect.equals("v; a=\"b c\"", HeaderValue("v", {"a": "b c"}).toString());
Expect.equals("v; a=\",\"", HeaderValue("v", {"a": ","}).toString());
Expect.equals(
"v; a=\"\\\\\\\"\"", HeaderValue("v", {"a": "\\\""}).toString());
Expect.equals("v; a=\"ø\"", HeaderValue("v", {"a": "ø"}).toString());
}
void testContentType() {
void check(ContentType contentType, String primaryType, String subType,
[Map<String, String> parameters]) {
Expect.equals(primaryType, contentType.primaryType);
Expect.equals(subType, contentType.subType);
Expect.equals("$primaryType/$subType", contentType.value);
if (parameters != null) {
Expect.equals(parameters.length, contentType.parameters.length);
parameters.forEach((String name, String value) {
Expect.equals(value, contentType.parameters[name]);
});
} else {
Expect.equals(0, contentType.parameters.length);
}
}
ContentType contentType;
contentType = new ContentType("", "");
Expect.equals("", contentType.primaryType);
Expect.equals("", contentType.subType);
Expect.equals("/", contentType.value);
Expect.throwsUnsupportedError(() => contentType.parameters["xxx"] = "yyy");
contentType = ContentType.parse("text/html");
check(contentType, "text", "html");
Expect.equals("text/html", contentType.toString());
contentType = new ContentType("text", "html", charset: "utf-8");
check(contentType, "text", "html", {"charset": "utf-8"});
Expect.equals("text/html; charset=utf-8", contentType.toString());
Expect.throwsUnsupportedError(() => contentType.parameters["xxx"] = "yyy");
contentType = new ContentType("text", "html",
parameters: {"CHARSET": "UTF-8", "xxx": "YYY"});
check(contentType, "text", "html", {"charset": "utf-8", "xxx": "YYY"});
String s = contentType.toString();
bool expectedToString = (s == "text/html; charset=utf-8; xxx=YYY" ||
s == "text/html; xxx=YYY; charset=utf-8");
Expect.isTrue(expectedToString);
contentType = ContentType.parse("text/html; CHARSET=UTF-8; xxx=YYY");
check(contentType, "text", "html", {"charset": "utf-8", "xxx": "YYY"});
Expect.throwsUnsupportedError(() => contentType.parameters["xxx"] = "yyy");
contentType = new ContentType("text", "html",
charset: "ISO-8859-1", parameters: {"CHARSET": "UTF-8", "xxx": "yyy"});
check(contentType, "text", "html", {"charset": "iso-8859-1", "xxx": "yyy"});
s = contentType.toString();
expectedToString = (s == "text/html; charset=iso-8859-1; xxx=yyy" ||
s == "text/html; xxx=yyy; charset=iso-8859-1");
Expect.isTrue(expectedToString);
contentType = ContentType.parse("text/html");
check(contentType, "text", "html");
contentType = ContentType.parse(" text/html ");
check(contentType, "text", "html");
contentType = ContentType.parse("text/html; charset=utf-8");
check(contentType, "text", "html", {"charset": "utf-8"});
contentType = ContentType.parse(" text/html ; charset = utf-8 ");
check(contentType, "text", "html", {"charset": "utf-8"});
contentType = ContentType.parse("text/html; charset=utf-8; xxx=yyy");
check(contentType, "text", "html", {"charset": "utf-8", "xxx": "yyy"});
contentType =
ContentType.parse(" text/html ; charset = utf-8 ; xxx=yyy ");
check(contentType, "text", "html", {"charset": "utf-8", "xxx": "yyy"});
contentType = ContentType.parse('text/html; charset=utf-8; xxx="yyy"');
check(contentType, "text", "html", {"charset": "utf-8", "xxx": "yyy"});
contentType =
ContentType.parse(" text/html ; charset = utf-8 ; xxx=yyy ");
check(contentType, "text", "html", {"charset": "utf-8", "xxx": "yyy"});
contentType = ContentType.parse("text/html; charset=;");
check(contentType, "text", "html", {"charset": ""});
contentType = ContentType.parse("text/html; charset;");
check(contentType, "text", "html", {"charset": null});
// Test builtin content types.
check(ContentType.text, "text", "plain", {"charset": "utf-8"});
check(ContentType.html, "text", "html", {"charset": "utf-8"});
check(ContentType.json, "application", "json", {"charset": "utf-8"});
check(ContentType.binary, "application", "octet-stream");
}
void testKnownContentTypes() {
// Well known content types used by the VM service.
ContentType.parse('text/html; charset=UTF-8');
ContentType.parse('application/dart; charset=UTF-8');
ContentType.parse('application/javascript; charset=UTF-8');
ContentType.parse('text/css; charset=UTF-8');
ContentType.parse('image/gif');
ContentType.parse('image/png');
ContentType.parse('image/jpeg');
ContentType.parse('image/jpeg');
ContentType.parse('image/svg+xml');
ContentType.parse('text/plain');
}
void testContentTypeCache() {
_HttpHeaders headers = new _HttpHeaders("1.1");
headers.set(HttpHeaders.contentTypeHeader, "text/html");
Expect.equals("text", headers.contentType.primaryType);
Expect.equals("html", headers.contentType.subType);
Expect.equals("text/html", headers.contentType.value);
headers.set(HttpHeaders.contentTypeHeader, "text/plain; charset=utf-8");
Expect.equals("text", headers.contentType.primaryType);
Expect.equals("plain", headers.contentType.subType);
Expect.equals("text/plain", headers.contentType.value);
headers.removeAll(HttpHeaders.contentTypeHeader);
Expect.isNull(headers.contentType);
}
void testCookie() {
test(String name, String value) {
void checkCookiesEquals(a, b) {
Expect.equals(a.name, b.name);
Expect.equals(a.value, b.value);
Expect.equals(a.expires, b.expires);
Expect.equals(a.toString(), b.toString());
}
void checkCookie(cookie, s) {
Expect.equals(s, cookie.toString());
var c = new _Cookie.fromSetCookieValue(s);
checkCookiesEquals(cookie, c);
}
Cookie cookie;
cookie = new Cookie(name, value);
Expect.equals("$name=$value; HttpOnly", cookie.toString());
DateTime date = new DateTime.utc(2014, DateTime.january, 5, 23, 59, 59, 0);
cookie.expires = date;
checkCookie(
cookie,
"$name=$value"
"; Expires=Sun, 05 Jan 2014 23:59:59 GMT"
"; HttpOnly");
cookie.maxAge = 567;
checkCookie(
cookie,
"$name=$value"
"; Expires=Sun, 05 Jan 2014 23:59:59 GMT"
"; Max-Age=567"
"; HttpOnly");
cookie.domain = "example.com";
checkCookie(
cookie,
"$name=$value"
"; Expires=Sun, 05 Jan 2014 23:59:59 GMT"
"; Max-Age=567"
"; Domain=example.com"
"; HttpOnly");
cookie.path = "/xxx";
checkCookie(
cookie,
"$name=$value"
"; Expires=Sun, 05 Jan 2014 23:59:59 GMT"
"; Max-Age=567"
"; Domain=example.com"
"; Path=/xxx"
"; HttpOnly");
cookie.secure = true;
checkCookie(
cookie,
"$name=$value"
"; Expires=Sun, 05 Jan 2014 23:59:59 GMT"
"; Max-Age=567"
"; Domain=example.com"
"; Path=/xxx"
"; Secure"
"; HttpOnly");
cookie.httpOnly = false;
checkCookie(
cookie,
"$name=$value"
"; Expires=Sun, 05 Jan 2014 23:59:59 GMT"
"; Max-Age=567"
"; Domain=example.com"
"; Path=/xxx"
"; Secure");
cookie.expires = null;
checkCookie(
cookie,
"$name=$value"
"; Max-Age=567"
"; Domain=example.com"
"; Path=/xxx"
"; Secure");
cookie.maxAge = null;
checkCookie(
cookie,
"$name=$value"
"; Domain=example.com"
"; Path=/xxx"
"; Secure");
cookie.domain = null;
checkCookie(
cookie,
"$name=$value"
"; Path=/xxx"
"; Secure");
cookie.path = null;
checkCookie(
cookie,
"$name=$value"
"; Secure");
cookie.secure = false;
checkCookie(cookie, "$name=$value");
}
test("name", "value");
test("abc", "def");
test("ABC", "DEF");
test("Abc", "Def");
test("SID", "sJdkjKSJD12343kjKj78");
}
void testInvalidCookie() {
Expect.throws(() => new _Cookie.fromSetCookieValue(""));
Expect.throws(() => new _Cookie.fromSetCookieValue("="));
Expect.throws(() => new _Cookie.fromSetCookieValue("=xxx"));
Expect.throws(() => new _Cookie.fromSetCookieValue("xxx"));
Expect.throws(
() => new _Cookie.fromSetCookieValue("xxx=yyy; expires=12 jan 2013"));
Expect.throws(() => new _Cookie.fromSetCookieValue("x x = y y"));
Expect.throws(() => new _Cookie("[4", "y"));
Expect.throws(() => new _Cookie("4", "y\""));
_HttpHeaders headers = new _HttpHeaders("1.1");
headers.set(
'Cookie', 'DARTSESSID=d3d6fdd78d51aaaf2924c32e991f4349; undefined');
Expect.equals('DARTSESSID', headers._parseCookies().single.name);
Expect.equals(
'd3d6fdd78d51aaaf2924c32e991f4349', headers._parseCookies().single.value);
}
void testHeaderLists() {
HttpHeaders.generalHeaders.forEach((x) => null);
HttpHeaders.entityHeaders.forEach((x) => null);
HttpHeaders.responseHeaders.forEach((x) => null);
HttpHeaders.requestHeaders.forEach((x) => null);
}
void testInvalidFieldName() {
void test(String field) {
_HttpHeaders headers = new _HttpHeaders("1.1");
Expect.throwsFormatException(() => headers.add(field, "value"));
Expect.throwsFormatException(() => headers.set(field, "value"));
Expect.throwsFormatException(() => headers.remove(field, "value"));
Expect.throwsFormatException(() => headers.removeAll(field));
}
test('\r');
test('\n');
test(',');
test('test\x00');
}
void testInvalidFieldValue() {
void test(value, {bool remove: true}) {
_HttpHeaders headers = new _HttpHeaders("1.1");
Expect.throwsFormatException(() => headers.add("field", value));
Expect.throwsFormatException(() => headers.set("field", value));
if (remove) {
Expect.throwsFormatException(() => headers.remove("field", value));
}
}
test('\r');
test('\n');
test('test\x00');
// Test we handle other types correctly.
test(new StringBuffer('\x00'), remove: false);
}
void testClear() {
_HttpHeaders headers = new _HttpHeaders("1.1");
headers.add("a", "b");
headers.contentLength = 7;
headers.chunkedTransferEncoding = true;
headers.clear();
Expect.isNull(headers["a"]);
Expect.equals(headers.contentLength, -1);
Expect.isFalse(headers.chunkedTransferEncoding);
}
void testFolding() {
_HttpHeaders headers = new _HttpHeaders("1.1");
headers.add("a", "b");
headers.add("a", "c");
headers.add("a", "d");
// no folding by default
Expect.isTrue(headers.toString().contains('b, c, d'));
// Header name should be case insensitive
headers.noFolding('A');
var str = headers.toString();
Expect.isTrue(str.contains(': b'));
Expect.isTrue(str.contains(': c'));
Expect.isTrue(str.contains(': d'));
}
void testLowercaseAdd() {
_HttpHeaders headers = new _HttpHeaders("1.1");
headers.add('A', 'a');
Expect.equals(headers['a'][0], headers['A'][0]);
Expect.equals(headers['A'][0], 'a');
headers.add('Foo', 'Foo', preserveHeaderCase: true);
Expect.equals(headers['Foo'][0], 'Foo');
// Header field is Foo.
Expect.isTrue(headers.toString().contains('Foo:'));
headers.add('FOo', 'FOo', preserveHeaderCase: true);
// Header field changes to FOo.
Expect.isTrue(headers.toString().contains('FOo:'));
headers.add('FOO', 'FOO', preserveHeaderCase: false);
// Header field
Expect.isTrue(!headers.toString().contains('Foo:'));
Expect.isTrue(!headers.toString().contains('FOo:'));
Expect.isTrue(headers.toString().contains('FOO'));
}
void testLowercaseSet() {
_HttpHeaders headers = new _HttpHeaders("1.1");
headers.add('test', 'lower cases');
// 'Test' should override 'test' entity
headers.set('TEST', 'upper cases', preserveHeaderCase: true);
Expect.isTrue(headers.toString().contains('TEST: upper cases'));
Expect.equals(1, headers['test'].length);
Expect.equals(headers['test'][0], 'upper cases');
// Latest header will be stored.
headers.set('Test', 'mixed cases', preserveHeaderCase: true);
Expect.isTrue(headers.toString().contains('Test: mixed cases'));
Expect.equals(1, headers['test'].length);
Expect.equals(headers['test'][0], 'mixed cases');
}
void testForEach() {
_HttpHeaders headers = new _HttpHeaders("1.1");
headers.add('header1', 'value 1');
headers.add('header2', 'value 2');
headers.add('HEADER1', 'value 3', preserveHeaderCase: true);
headers.add('HEADER3', 'value 4', preserveHeaderCase: true);
BytesBuilder builder = BytesBuilder();
headers._build(builder);
Expect.isTrue(utf8.decode(builder.toBytes()).contains('HEADER1'));
bool myHeader1 = false;
bool myHeader2 = false;
bool myHeader3 = false;
int totalValues = 0;
headers.forEach((String name, List<String> values) {
totalValues += values.length;
if (name == "HEADER1") {
myHeader1 = true;
Expect.isTrue(values.indexOf("value 1") != -1);
Expect.isTrue(values.indexOf("value 3") != -1);
}
if (name == "header2") {
myHeader2 = true;
Expect.isTrue(values.indexOf("value 2") != -1);
}
if (name == "HEADER3") {
myHeader3 = true;
Expect.isTrue(values.indexOf("value 4") != -1);
}
});
Expect.isTrue(myHeader1);
Expect.isTrue(myHeader2);
Expect.isTrue(myHeader3);
Expect.equals(4, totalValues);
}
main() {
testMultiValue();
testDate();
testExpires();
testIfModifiedSince();
testHost();
testTransferEncoding();
testEnumeration();
testHeaderValue();
testContentType();
testKnownContentTypes();
testContentTypeCache();
testCookie();
testInvalidCookie();
testHeaderLists();
testInvalidFieldName();
testInvalidFieldValue();
testClear();
testFolding();
testLowercaseAdd();
testLowercaseSet();
testForEach();
}

View file

@ -1,849 +0,0 @@
// 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.
// @dart = 2.6
library dart._http;
import "dart:async";
import "dart:collection";
import "dart:convert";
import "dart:developer";
import "dart:io";
import "dart:isolate";
import "dart:math";
import "dart:typed_data";
import "package:expect/expect.dart";
part "../../../sdk/lib/_http/crypto.dart";
part "../../../sdk/lib/_http/embedder_config.dart";
part "../../../sdk/lib/_http/http_impl.dart";
part "../../../sdk/lib/_http/http_date.dart";
part "../../../sdk/lib/_http/http_parser.dart";
part "../../../sdk/lib/_http/http_headers.dart";
part "../../../sdk/lib/_http/http_session.dart";
class HttpParserTest {
static void runAllTests() {
testParseRequest();
testParseResponse();
testParseInvalidRequest();
testParseInvalidResponse();
}
static void _testParseRequest(
String request, String expectedMethod, String expectedUri,
{int expectedTransferLength: 0,
int expectedBytesReceived: 0,
Map<String, String> expectedHeaders: null,
bool chunked: false,
bool upgrade: false,
int unparsedLength: 0,
bool connectionClose: false,
String expectedVersion: "1.1"}) {
StreamController<Uint8List> controller;
void reset() {
_HttpParser httpParser = new _HttpParser.requestParser();
controller = new StreamController(sync: true);
var port1 = new ReceivePort();
var port2 = new ReceivePort();
String method;
Uri uri;
_HttpHeaders headers;
int contentLength;
int bytesReceived;
int unparsedBytesReceived;
bool upgraded;
httpParser.listenToStream(controller.stream);
var subscription = httpParser.listen((incoming) {
method = incoming.method;
uri = incoming.uri;
headers = incoming.headers;
upgraded = incoming.upgraded;
Expect.equals(upgrade, upgraded);
if (!chunked) {
Expect.equals(expectedTransferLength, incoming.transferLength);
} else {
Expect.equals(-1, incoming.transferLength);
}
if (expectedHeaders != null) {
expectedHeaders.forEach((String name, String value) =>
Expect.equals(value, headers[name][0]));
}
incoming.listen((List<int> data) {
Expect.isFalse(upgraded);
bytesReceived += data.length;
}, onDone: () {
port2.close();
Expect.equals(expectedMethod, method);
Expect.stringEquals(expectedUri, uri.toString());
Expect.equals(expectedVersion, headers.protocolVersion);
if (upgrade) {
Expect.equals(0, bytesReceived);
// port1 is closed by the listener on the detached data.
} else {
Expect.equals(expectedBytesReceived, bytesReceived);
}
});
if (upgraded) {
port1.close();
httpParser.detachIncoming().listen((List<int> data) {
unparsedBytesReceived += data.length;
}, onDone: () {
Expect.equals(unparsedLength, unparsedBytesReceived);
port2.close();
});
}
incoming.dataDone.then((_) {
port1.close();
});
});
method = null;
uri = null;
headers = null;
bytesReceived = 0;
unparsedBytesReceived = 0;
upgraded = false;
}
void testWrite(List<int> requestData, [int chunkSize = -1]) {
if (chunkSize == -1) chunkSize = requestData.length;
reset();
for (int pos = 0; pos < requestData.length; pos += chunkSize) {
int end = min(requestData.length, pos + chunkSize);
controller.add(requestData.sublist(pos, end));
}
controller.close();
}
// Test parsing the request three times delivering the data in
// different chunks.
List<int> requestData = new Uint8List.fromList(request.codeUnits);
testWrite(requestData);
testWrite(requestData, 10);
testWrite(requestData, 1);
}
static void _testParseRequestLean(
String request, String expectedMethod, String expectedUri,
{int expectedTransferLength: 0,
int expectedBytesReceived: 0,
Map<String, String> expectedHeaders: null,
bool chunked: false,
bool upgrade: false,
int unparsedLength: 0,
bool connectionClose: false,
String expectedVersion: "1.1"}) {
_testParseRequest(request, expectedMethod, expectedUri,
expectedTransferLength: expectedTransferLength,
expectedBytesReceived: expectedBytesReceived,
expectedHeaders: expectedHeaders,
chunked: chunked,
upgrade: upgrade,
unparsedLength: unparsedLength,
connectionClose: connectionClose,
expectedVersion: expectedVersion);
// Same test but with only \n instead of \r\n terminating each header line.
_testParseRequest(request.replaceAll('\r', ''), expectedMethod, expectedUri,
expectedTransferLength: expectedTransferLength,
expectedBytesReceived: expectedBytesReceived,
expectedHeaders: expectedHeaders,
chunked: chunked,
upgrade: upgrade,
unparsedLength: unparsedLength,
connectionClose: connectionClose,
expectedVersion: expectedVersion);
}
static void _testParseInvalidRequest(String request) {
_HttpParser httpParser;
bool errorCalled;
StreamController<Uint8List> controller;
void reset() {
httpParser = new _HttpParser.requestParser();
controller = new StreamController(sync: true);
var port = new ReceivePort();
httpParser.listenToStream(controller.stream);
var subscription = httpParser.listen((incoming) {
Expect.fail("Expected request");
});
subscription.onError((e) {
errorCalled = true;
});
subscription.onDone(() {
port.close();
Expect.isTrue(errorCalled);
});
errorCalled = false;
}
void testWrite(List<int> requestData, [int chunkSize = -1]) {
if (chunkSize == -1) chunkSize = requestData.length;
reset();
for (int pos = 0;
pos < requestData.length && !errorCalled;
pos += chunkSize) {
int end = min(requestData.length, pos + chunkSize);
controller.add(requestData.sublist(pos, end));
}
controller.close();
}
// Test parsing the request three times delivering the data in
// different chunks.
List<int> requestData = new Uint8List.fromList(request.codeUnits);
testWrite(requestData);
testWrite(requestData, 10);
testWrite(requestData, 1);
}
static void _testParseResponse(
String response, int expectedStatusCode, String expectedReasonPhrase,
{int expectedTransferLength: 0,
int expectedBytesReceived: 0,
Map<String, String> expectedHeaders: null,
bool chunked: false,
bool close: false,
String responseToMethod: null,
bool connectionClose: false,
bool upgrade: false,
int unparsedLength: 0,
String expectedVersion: "1.1"}) {
StreamController<Uint8List> controller;
bool upgraded;
void reset() {
_HttpParser httpParser;
bool headersCompleteCalled;
bool dataEndCalled;
bool dataEndClose;
int statusCode;
String reasonPhrase;
_HttpHeaders headers;
int contentLength;
int bytesReceived;
httpParser = new _HttpParser.responseParser();
controller = new StreamController(sync: true);
var port = new ReceivePort();
httpParser.listenToStream(controller.stream);
int doneCallCount = 0;
// Called when done parsing entire message and done parsing body.
// Only executed when both are done.
void whenDone() {
doneCallCount++;
if (doneCallCount < 2) return;
Expect.equals(expectedVersion, headers.protocolVersion);
Expect.equals(expectedStatusCode, statusCode);
Expect.equals(expectedReasonPhrase, reasonPhrase);
Expect.isTrue(headersCompleteCalled);
Expect.equals(expectedBytesReceived, bytesReceived);
if (!upgrade) {
Expect.isTrue(dataEndCalled);
if (close) Expect.isTrue(dataEndClose);
Expect.equals(dataEndClose, connectionClose);
}
}
var subscription = httpParser.listen((incoming) {
port.close();
statusCode = incoming.statusCode;
reasonPhrase = incoming.reasonPhrase;
headers = incoming.headers;
Expect.isFalse(headersCompleteCalled);
if (!chunked && !close) {
Expect.equals(expectedTransferLength, incoming.transferLength);
} else {
Expect.equals(-1, incoming.transferLength);
}
if (expectedHeaders != null) {
expectedHeaders.forEach((String name, String value) {
Expect.equals(value, headers[name][0]);
});
}
Expect.equals(upgrade, httpParser.upgrade);
headersCompleteCalled = true;
incoming.listen((List<int> data) {
Expect.isTrue(headersCompleteCalled);
bytesReceived += data.length;
}, onDone: () {
dataEndCalled = true;
dataEndClose = close;
whenDone();
});
}, onDone: whenDone);
headersCompleteCalled = false;
dataEndCalled = false;
dataEndClose = null;
statusCode = -1;
reasonPhrase = null;
headers = null;
bytesReceived = 0;
}
void testWrite(List<int> requestData, [int chunkSize = -1]) {
if (chunkSize == -1) chunkSize = requestData.length;
reset();
for (int pos = 0; pos < requestData.length; pos += chunkSize) {
int end = min(requestData.length, pos + chunkSize);
controller.add(requestData.sublist(pos, end));
}
if (close) controller.close();
}
// Test parsing the request three times delivering the data in
// different chunks.
List<int> responseData = new Uint8List.fromList(response.codeUnits);
testWrite(responseData);
testWrite(responseData, 10);
testWrite(responseData, 1);
}
static void _testParseInvalidResponse(String response, [bool close = false]) {
void testWrite(List<int> requestData, [int chunkSize = -1]) {
_HttpParser httpParser = new _HttpParser.responseParser();
StreamController<Uint8List> controller = new StreamController(sync: true);
bool errorCalled = false;
if (chunkSize == -1) chunkSize = requestData.length;
var port = new ReceivePort();
httpParser.listenToStream(controller.stream);
var subscription = httpParser.listen((incoming) {
incoming.listen((data) {}, onError: (e) {
Expect.isFalse(errorCalled);
errorCalled = true;
});
});
subscription.onError((e) {
Expect.isFalse(errorCalled);
errorCalled = true;
});
subscription.onDone(() {
port.close();
Expect.isTrue(errorCalled);
});
errorCalled = false;
for (int pos = 0;
pos < requestData.length && !errorCalled;
pos += chunkSize) {
int end = min(requestData.length, pos + chunkSize);
controller.add(requestData.sublist(pos, end));
}
controller.close();
}
// Test parsing the request three times delivering the data in
// different chunks.
List<int> responseData = new Uint8List.fromList(response.codeUnits);
testWrite(responseData);
testWrite(responseData, 10);
testWrite(responseData, 1);
}
static void testParseRequest() {
String request;
Map<String, String> headers;
var methods = [
// RFC 2616 methods.
"OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT",
// WebDAV methods from RFC 4918.
"PROPFIND", "PROPPATCH", "MKCOL", "COPY", "MOVE", "LOCK", "UNLOCK",
// WebDAV methods from RFC 5323.
"SEARCH",
// Methods with HTTP prefix.
"H", "HT", "HTT", "HTTP", "HX", "HTX", "HTTX", "HTTPX"
];
methods = ['GET'];
methods.forEach((method) {
request = "$method / HTTP/1.1\r\n\r\n";
_testParseRequestLean(request, method, "/");
request = "$method /index.html HTTP/1.1\r\n\r\n";
_testParseRequestLean(request, method, "/index.html");
});
request = "GET / HTTP/1.0\r\n\r\n";
_testParseRequestLean(request, "GET", "/",
expectedVersion: "1.0", connectionClose: true);
request = "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n";
_testParseRequestLean(request, "GET", "/", expectedVersion: "1.0");
request = """
POST /test HTTP/1.1\r
AAA: AAA\r
\r
""";
_testParseRequestLean(request, "POST", "/test");
request = """
POST /test HTTP/1.1\r
\r
""";
_testParseRequestLean(request, "POST", "/test");
request = """
POST /test HTTP/1.1\r
Header-A: AAA\r
X-Header-B: bbb\r
\r
""";
headers = new Map();
headers["header-a"] = "AAA";
headers["x-header-b"] = "bbb";
_testParseRequestLean(request, "POST", "/test", expectedHeaders: headers);
request = """
POST /test HTTP/1.1\r
Empty-Header-1:\r
Empty-Header-2:\r
\r
\r
""";
headers = new Map();
headers["empty-header-1"] = "";
headers["empty-header-2"] = "";
_testParseRequestLean(request, "POST", "/test", expectedHeaders: headers);
request = """
POST /test HTTP/1.1\r
Header-A: AAA\r
X-Header-B:\t \t bbb\r
\r
""";
headers = new Map();
headers["header-a"] = "AAA";
headers["x-header-b"] = "bbb";
_testParseRequestLean(request, "POST", "/test", expectedHeaders: headers);
request = """
POST /test HTTP/1.1\r
Header-A: AA\r
A\r
X-Header-B: b\r
b\r
\t b\r
\r
""";
headers = new Map();
headers["header-a"] = "AAA";
headers["x-header-b"] = "bbb";
_testParseRequestLean(request, "POST", "/test", expectedHeaders: headers);
// _testParseRequestLean encodes the request as ISO-8859-1. Test that the
// HTTP parser decodes header values as ISO-8859-1.
request = """
POST /test HTTP/1.1\r
latin1: blåbærgrød\r
\r
""";
headers = new Map();
headers["latin1"] = "blåbærgrød";
_testParseRequestLean(request, "POST", "/test", expectedHeaders: headers);
request = """
POST /test HTTP/1.1\r
Content-Length: 10\r
\r
0123456789""";
_testParseRequestLean(request, "POST", "/test",
expectedTransferLength: 10, expectedBytesReceived: 10);
// Test connection close header.
request = "GET /test HTTP/1.1\r\nConnection: close\r\n\r\n";
_testParseRequest(request, "GET", "/test", connectionClose: true);
// Test chunked encoding.
request = """
POST /test HTTP/1.1\r
Transfer-Encoding: chunked\r
\r
5\r
01234\r
5\r
56789\r
0\r\n\r\n""";
_testParseRequest(request, "POST", "/test",
expectedTransferLength: -1, expectedBytesReceived: 10, chunked: true);
// Test mixing chunked encoding and content length (content length
// is ignored).
request = """
POST /test HTTP/1.1\r
Content-Length: 7\r
Transfer-Encoding: chunked\r
\r
5\r
01234\r
5\r
56789\r
0\r\n\r\n""";
_testParseRequest(request, "POST", "/test",
expectedTransferLength: -1, expectedBytesReceived: 10, chunked: true);
// Test mixing chunked encoding and content length (content length
// is ignored).
request = """
POST /test HTTP/1.1\r
Transfer-Encoding: chunked\r
Content-Length: 3\r
\r
5\r
01234\r
5\r
56789\r
0\r\n\r\n""";
_testParseRequest(request, "POST", "/test",
expectedTransferLength: -1, expectedBytesReceived: 10, chunked: true);
// Test upper and lower case hex digits in chunked encoding.
request = """
POST /test HTTP/1.1\r
Transfer-Encoding: chunked\r
\r
1E\r
012345678901234567890123456789\r
1e\r
012345678901234567890123456789\r
0\r\n\r\n""";
_testParseRequest(request, "POST", "/test",
expectedTransferLength: -1, expectedBytesReceived: 60, chunked: true);
// Test chunk extensions in chunked encoding.
request = """
POST /test HTTP/1.1\r
Transfer-Encoding: chunked\r
\r
1E;xxx\r
012345678901234567890123456789\r
1E;yyy=zzz\r
012345678901234567890123456789\r
0\r\n\r\n""";
_testParseRequest(request, "POST", "/test",
expectedTransferLength: -1, expectedBytesReceived: 60, chunked: true);
// Test HTTP upgrade.
request = """
GET /irc HTTP/1.1\r
Upgrade: irc/1.2\r
Connection: Upgrade\r
\r\n\x01\x01\x01\x01\x01\x02\x02\x02\x02\xFF""";
headers = new Map();
headers["upgrade"] = "irc/1.2";
_testParseRequest(request, "GET", "/irc",
expectedHeaders: headers, upgrade: true, unparsedLength: 10);
// Test HTTP upgrade with protocol data.
request = """
GET /irc HTTP/1.1\r
Upgrade: irc/1.2\r
Connection: Upgrade\r
\r\n""";
headers = new Map();
headers["upgrade"] = "irc/1.2";
_testParseRequest(request, "GET", "/irc",
expectedHeaders: headers, upgrade: true);
// Test websocket upgrade.
request = """
GET /chat HTTP/1.1\r
Host: server.example.com\r
Upgrade: websocket\r
Connection: Upgrade\r
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r
Origin: http://example.com\r
Sec-WebSocket-Version: 13\r
\r\n""";
headers = new Map();
headers["host"] = "server.example.com";
headers["upgrade"] = "websocket";
headers["sec-websocket-key"] = "dGhlIHNhbXBsZSBub25jZQ==";
headers["origin"] = "http://example.com";
headers["sec-websocket-version"] = "13";
_testParseRequest(request, "GET", "/chat",
expectedHeaders: headers, upgrade: true);
// Test websocket upgrade with protocol data. NOTE: When using the
// WebSocket protocol this should never happen as the client
// should not send protocol data before processing the request
// part of the opening handshake. However the HTTP parser should
// still handle this.
request = """
GET /chat HTTP/1.1\r
Host: server.example.com\r
Upgrade: websocket\r
Connection: Upgrade\r
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r
Origin: http://example.com\r
Sec-WebSocket-Version: 13\r
\r\n0123456""";
headers = new Map();
headers["host"] = "server.example.com";
headers["upgrade"] = "websocket";
headers["sec-websocket-key"] = "dGhlIHNhbXBsZSBub25jZQ==";
headers["origin"] = "http://example.com";
headers["sec-websocket-version"] = "13";
_testParseRequest(request, "GET", "/chat",
expectedHeaders: headers, upgrade: true, unparsedLength: 7);
}
static void testParseResponse() {
String response;
Map<String, String> headers;
response = "HTTP/1.1 100 Continue\r\nContent-Length: 0\r\n\r\n";
_testParseResponse(response, 100, "Continue");
response = "HTTP/1.1 100 Continue\r\nContent-Length: 0\r\n\r\n";
_testParseResponse(response, 100, "Continue");
response = "HTTP/1.1 100 Continue\r\nContent-Length: 10\r\n\r\n";
_testParseResponse(response, 100, "Continue",
expectedTransferLength: 10, expectedBytesReceived: 0);
response = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n"
"Connection: Close\r\n\r\n";
_testParseResponse(response, 200, "OK", connectionClose: true);
response = "HTTP/1.0 200 OK\r\nContent-Length: 0\r\n\r\n";
_testParseResponse(response, 200, "OK",
expectedVersion: "1.0", connectionClose: true);
response = "HTTP/1.0 200 OK\r\nContent-Length: 0\r\n"
"Connection: Keep-Alive\r\n\r\n";
_testParseResponse(response, 200, "OK", expectedVersion: "1.0");
response = "HTTP/1.1 204 No Content\r\nContent-Length: 11\r\n\r\n";
_testParseResponse(response, 204, "No Content",
expectedTransferLength: 11, expectedBytesReceived: 0);
response = "HTTP/1.1 304 Not Modified\r\nContent-Length: 12\r\n\r\n";
_testParseResponse(response, 304, "Not Modified",
expectedTransferLength: 12, expectedBytesReceived: 0);
response = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n";
_testParseResponse(response, 200, "OK");
response = "HTTP/1.1 404 Not found\r\nContent-Length: 0\r\n\r\n";
_testParseResponse(response, 404, "Not found");
response = "HTTP/1.1 500 Server error\r\nContent-Length: 0\r\n\r\n";
_testParseResponse(response, 500, "Server error");
// Test response to HEAD request.
response = """
HTTP/1.1 200 OK\r
Content-Length: 20\r
Content-Type: text/html\r
\r\n""";
headers = new Map();
headers["content-length"] = "20";
headers["content-type"] = "text/html";
_testParseResponse(response, 200, "OK",
responseToMethod: "HEAD",
expectedTransferLength: 20,
expectedBytesReceived: 0,
expectedHeaders: headers);
// _testParseRequestLean encodes the request as ISO-8859-1. Test that the
// HTTP parser decodes header values as ISO-8859-1.
response = """
HTTP/1.1 200 OK\r
Content-Length: 0\r
test-latin1: blåbærgrød\r
\r\n""";
headers = new Map();
headers["content-length"] = "0";
headers["test-latin1"] = "blåbærgrød";
_testParseResponse(response, 200, "OK", expectedHeaders: headers);
// Test content.
response = """
HTTP/1.1 200 OK\r
Content-Length: 20\r
\r
01234567890123456789""";
_testParseResponse(response, 200, "OK",
expectedTransferLength: 20, expectedBytesReceived: 20);
// Test upper and lower case hex digits in chunked encoding.
response = """
HTTP/1.1 200 OK\r
Transfer-Encoding: chunked\r
\r
1A\r
01234567890123456789012345\r
1f\r
0123456789012345678901234567890\r
0\r\n\r\n""";
_testParseResponse(response, 200, "OK",
expectedTransferLength: -1, expectedBytesReceived: 57, chunked: true);
// Test connection close header.
response = """
HTTP/1.1 200 OK\r
Content-Length: 0\r
Connection: close\r
\r\n""";
_testParseResponse(response, 200, "OK", connectionClose: true);
// Test HTTP response without any transfer length indications
// where closing the connections indicates end of body.
response = """
HTTP/1.1 200 OK\r
\r
01234567890123456789012345
0123456789012345678901234567890
""";
_testParseResponse(response, 200, "OK",
expectedTransferLength: -1,
expectedBytesReceived: 59,
close: true,
connectionClose: true);
// Test HTTP upgrade.
response = """
HTTP/1.1 101 Switching Protocols\r
Upgrade: irc/1.2\r
Connection: Upgrade\r
\r\n""";
headers = new Map();
headers["upgrade"] = "irc/1.2";
_testParseResponse(response, 101, "Switching Protocols",
expectedHeaders: headers, upgrade: true);
// Test HTTP upgrade with protocol data.
response = """
HTTP/1.1 101 Switching Protocols\r
Upgrade: irc/1.2\r
Connection: Upgrade\r
\r\n\x00\x10\x20\x30\x40\x50\x60\x70\x80\x90\xA0\xB0\xC0\xD0\xE0\xF0""";
headers = new Map();
headers["upgrade"] = "irc/1.2";
_testParseResponse(response, 101, "Switching Protocols",
expectedHeaders: headers, upgrade: true, unparsedLength: 16);
// Test websocket upgrade.
response = """
HTTP/1.1 101 Switching Protocols\r
Upgrade: websocket\r
Connection: Upgrade\r
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r
\r\n""";
headers = new Map();
headers["upgrade"] = "websocket";
headers["sec-websocket-accept"] = "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=";
_testParseResponse(response, 101, "Switching Protocols",
expectedHeaders: headers, upgrade: true);
// Test websocket upgrade with protocol data.
response = """
HTTP/1.1 101 Switching Protocols\r
Upgrade: websocket\r
Connection: Upgrade\r
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r
\r\nABCD""";
headers = new Map();
headers["upgrade"] = "websocket";
headers["sec-websocket-accept"] = "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=";
_testParseResponse(response, 101, "Switching Protocols",
expectedHeaders: headers, upgrade: true, unparsedLength: 4);
}
static void testParseInvalidRequest() {
String request;
request = "GET /\r\n\r\n";
_testParseInvalidRequest(request);
request = "GET / \r\n\r\n";
_testParseInvalidRequest(request);
request = "/ HTTP/1.1\r\n\r\n";
_testParseInvalidRequest(request);
request = "GET HTTP/1.1\r\n\r\n";
_testParseInvalidRequest(request);
request = " / HTTP/1.1\r\n\r\n";
_testParseInvalidRequest(request);
request = "@ / HTTP/1.1\r\n\r\n";
_testParseInvalidRequest(request);
request = "GET / TTP/1.1\r\n\r\n";
_testParseInvalidRequest(request);
request = "GET / HTTP/1.\r\n\r\n";
_testParseInvalidRequest(request);
request = "GET / HTTP/1.1\r\nKeep-Alive: False\r\nbadheader\r\n\r\n";
_testParseInvalidRequest(request);
}
static void testParseInvalidResponse() {
String response;
response = "HTTP/1.1\r\nContent-Length: 0\r\n\r\n";
_testParseInvalidResponse(response);
response = "HTTP/1.1 \r\nContent-Length: 0\r\n\r\n";
_testParseInvalidResponse(response);
response = "HTTP/1.1 200\r\nContent-Length: 0\r\n\r\n";
_testParseInvalidResponse(response);
response = "HTTP/1.1 200 \r\nContent-Length: 0\r\n\r\n";
_testParseInvalidResponse(response);
response = "HTTP/1.1 OK\r\nContent-Length: 0\r\n\r\n";
_testParseInvalidResponse(response);
response = "HTTP/1.1 20A OK\r\nContent-Length: 0\r\n\r\n";
_testParseInvalidResponse(response);
response = "200 OK\r\nContent-Length: 0\r\n\r\n";
_testParseInvalidResponse(response);
response = "HTTP/1. 200 OK\r\nContent-Length: 0\r\n\r\n";
_testParseInvalidResponse(response);
response = "HTTP/1.1 200 O\rK\r\nContent-Length: 0\r\n\r\n";
_testParseInvalidResponse(response);
response = "HTTP/1.1 000 OK\r\nContent-Length: 0\r\n\r\n";
_testParseInvalidResponse(response);
response = "HTTP/1.1 999 Server Error\r\nContent-Length: 0\r\n\r\n";
_testParseInvalidResponse(response);
response = "HTTP/1.1 200 OK\r\nContent-Length: x\r\n\r\n";
_testParseInvalidResponse(response);
response = "HTTP/1.1 200 OK\r\nbadheader\r\n\r\n";
_testParseInvalidResponse(response);
response = """
HTTP/1.1 200 OK\r
Transfer-Encoding: chunked\r
\r
1A\r
01234567890123456789012345\r
1g\r
0123456789012345678901234567890\r
0\r\n\r\n""";
_testParseInvalidResponse(response);
}
}
void main() {
HttpParserTest.runAllTests();
}

View file

@ -1,103 +0,0 @@
// 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
// OtherResources=certificates/server_chain.pem
// OtherResources=certificates/server_key.pem
// @dart = 2.6
library dart._http;
import "dart:async";
import "dart:io";
import "dart:math";
import "dart:typed_data";
import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";
import "package:path/path.dart";
part "../../../sdk/lib/_http/crypto.dart";
const String webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
const String CERT_NAME = 'localhost_cert';
const String HOST_NAME = 'localhost';
String localFile(path) => Platform.script.resolve(path).toFilePath();
SecurityContext serverContext = new SecurityContext()
..useCertificateChain(localFile('certificates/server_chain.pem'))
..usePrivateKey(localFile('certificates/server_key.pem'),
password: 'dartdart');
SecurityContext clientContext = new SecurityContext()
..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
/**
* A SecurityConfiguration lets us run the tests over HTTP or HTTPS.
*/
class SecurityConfiguration {
final bool secure;
SecurityConfiguration({bool this.secure});
Future<HttpServer> createServer({int backlog: 0}) => secure
? HttpServer.bindSecure(HOST_NAME, 0, serverContext, backlog: backlog)
: HttpServer.bind(HOST_NAME, 0, backlog: backlog);
Future<WebSocket> createClient(int port) =>
// TODO(whesse): Add a client context argument to WebSocket.connect.
WebSocket.connect('${secure ? "wss" : "ws"}://$HOST_NAME:$port/');
void testForceCloseServerEnd(int totalConnections) {
createServer().then((server) {
server.listen((request) {
var response = request.response;
response.statusCode = HttpStatus.switchingProtocols;
response.headers.set(HttpHeaders.connectionHeader, "upgrade");
response.headers.set(HttpHeaders.upgradeHeader, "websocket");
String key = request.headers.value("Sec-WebSocket-Key");
_SHA1 sha1 = new _SHA1();
sha1.add("$key$webSocketGUID".codeUnits);
String accept = _CryptoUtils.bytesToBase64(sha1.close());
response.headers.add("Sec-WebSocket-Accept", accept);
response.headers.contentLength = 0;
response.detachSocket().then((socket) {
socket.destroy();
});
});
int closeCount = 0;
for (int i = 0; i < totalConnections; i++) {
createClient(server.port).then((webSocket) {
webSocket.add("Hello, world!");
webSocket.listen((message) {
Expect.fail("unexpected message");
}, onDone: () {
closeCount++;
if (closeCount == totalConnections) {
server.close();
}
});
});
}
});
}
void runTests() {
testForceCloseServerEnd(10);
}
}
main() {
asyncStart();
new SecurityConfiguration(secure: false).runTests();
// TODO(whesse): WebSocket.connect needs an optional context: parameter
// new SecurityConfiguration(secure: true).runTests();
asyncEnd();
}

View file

@ -1,62 +0,0 @@
// 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.6
library dart._http;
import "package:expect/expect.dart";
import "dart:async";
import "dart:io";
import "dart:math";
import "dart:typed_data";
part "../../../sdk/lib/_http/crypto.dart";
const String webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
void testPing(int totalConnections) {
HttpServer.bind('localhost', 0).then((server) {
int closed = 0;
server.listen((request) {
var response = request.response;
response.statusCode = HttpStatus.switchingProtocols;
response.headers.set(HttpHeaders.connectionHeader, "upgrade");
response.headers.set(HttpHeaders.upgradeHeader, "websocket");
String key = request.headers.value("Sec-WebSocket-Key");
_SHA1 sha1 = new _SHA1();
sha1.add("$key$webSocketGUID".codeUnits);
String accept = _CryptoUtils.bytesToBase64(sha1.close());
response.headers.add("Sec-WebSocket-Accept", accept);
response.headers.contentLength = 0;
response.detachSocket().then((socket) {
socket.destroy();
});
});
int closeCount = 0;
for (int i = 0; i < totalConnections; i++) {
WebSocket.connect('ws://localhost:${server.port}').then((webSocket) {
webSocket.pingInterval = const Duration(milliseconds: 100);
webSocket.listen((message) {
Expect.fail("unexpected message");
}, onDone: () {
closeCount++;
if (closeCount == totalConnections) {
server.close();
}
});
});
}
});
}
void main() {
testPing(10);
}

View file

@ -1,243 +0,0 @@
// Copyright (c) 2012, 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.
// @dart = 2.6
library dart._http;
import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";
import "dart:async";
import "dart:collection";
import "dart:convert";
import "dart:developer";
import "dart:io";
import "dart:math";
import "dart:typed_data";
import "dart:isolate";
part "../../../sdk/lib/_http/crypto.dart";
part "../../../sdk/lib/_http/embedder_config.dart";
part "../../../sdk/lib/_http/http_impl.dart";
part "../../../sdk/lib/_http/http_date.dart";
part "../../../sdk/lib/_http/http_parser.dart";
part "../../../sdk/lib/_http/http_headers.dart";
part "../../../sdk/lib/_http/http_session.dart";
part "../../../sdk/lib/_http/websocket.dart";
part "../../../sdk/lib/_http/websocket_impl.dart";
class WebSocketFrame {
WebSocketFrame(int opcode, List<int> data);
}
// Class that when hooked up to the web socket protocol transformer will
// collect the message and expect it to be equal to the
// expectedMessage field when fully received.
class WebSocketMessageCollector {
List<int> expectedMessage;
int messageCount = 0;
var data;
Function onClosed;
WebSocketMessageCollector(Stream stream,
[List<int> this.expectedMessage = null]) {
stream.listen(onMessageData, onDone: onClosed, onError: onError);
}
void onMessageData(buffer) {
if (buffer is String) {
buffer = utf8.encode(buffer);
}
Expect.listEquals(expectedMessage, buffer);
messageCount++;
data = buffer;
}
void onError(e, trace) {
String msg = "Unexpected error $e";
if (trace != null) msg += "\nStackTrace: $trace";
Expect.fail(msg);
}
}
// Web socket constants.
const int FRAME_OPCODE_TEXT = 1;
const int FRAME_OPCODE_BINARY = 2;
// Function for building a web socket frame.
List<int> createFrame(bool fin, int opcode, int maskingKey, List<int> data,
int offset, int count) {
int frameSize = 2;
if (count > 125) frameSize += 2;
if (count > 65535) frameSize += 6;
frameSize += count;
// No masking.
assert(maskingKey == null);
List<int> frame = new Uint8List(frameSize);
int frameIndex = 0;
frame[frameIndex++] = (fin ? 0x80 : 0x00) | opcode;
if (count < 126) {
frame[frameIndex++] = count;
} else if (count < 65536) {
frame[frameIndex++] = 126;
frame[frameIndex++] = count >> 8;
frame[frameIndex++] = count & 0xFF;
} else {
frame[frameIndex++] = 127;
for (int i = 0; i < 8; i++) {
frame[frameIndex++] = count >> ((7 - i) * 8) & 0xFF;
}
}
frame.setRange(frameIndex, frameIndex + count, data, offset);
return frame;
}
// Test processing messages which are sent in a single frame.
void testFullMessages() {
void testMessage(int opcode, List<int> message) {
int messageCount = 0;
// Use the same web socket protocol transformer for all frames.
var transformer = new _WebSocketProtocolTransformer();
var controller = new StreamController<List<int>>(sync: true);
WebSocketMessageCollector mc = new WebSocketMessageCollector(
controller.stream.transform(transformer), message);
List<int> frame =
createFrame(true, opcode, null, message, 0, message.length);
// Update the transformer with one big chunk.
messageCount++;
controller.add(frame);
mc.onClosed = () {
Expect.isNotNull(mc.data);
Expect.equals(0, transformer._state);
mc.data = null;
// Only run this part on small messages.
if (message.length < 1000) {
// Update the transformer one byte at the time.
messageCount++;
for (int i = 0; i < frame.length; i++) {
controller.add(<int>[frame[i]]);
}
Expect.equals(0, transformer._state);
Expect.isNotNull(mc.data);
mc.data = null;
// Update the transformer two bytes at the time.
messageCount++;
for (int i = 0; i < frame.length; i += 2) {
controller.add(frame.sublist(i, min(i + 2, frame.length)));
}
Expect.equals(0, transformer._state);
Expect.isNotNull(mc.data);
}
Expect.equals(messageCount, mc.messageCount);
print("Messages test, messages $messageCount");
};
controller.close();
}
void runTest(int from, int to, int step) {
for (int messageLength = from; messageLength < to; messageLength += step) {
List<int> message = new List<int>(messageLength);
for (int i = 0; i < messageLength; i++) message[i] = i & 0x7F;
testMessage(FRAME_OPCODE_TEXT, message);
for (int i = 0; i < messageLength; i++) message[i] = i & 0xFF;
testMessage(FRAME_OPCODE_BINARY, message);
}
}
// Test different message sizes.
runTest(0, 10, 1);
runTest(120, 130, 1);
runTest(0, 1000, 100);
runTest(65534, 65537, 1);
}
// Test processing of frames which are split into fragments.
void testFragmentedMessages() {
// Use the same web socket protocol transformer for all frames.
var transformer = new _WebSocketProtocolTransformer();
var controller = new StreamController<List<int>>(sync: true);
WebSocketMessageCollector mc =
new WebSocketMessageCollector(controller.stream.transform(transformer));
int messageCount = 0;
int frameCount = 0;
void testFragmentMessage(int opcode, List<int> message, int fragmentSize) {
messageCount++;
int messageIndex = 0;
int remaining = message.length;
bool firstFrame = true;
bool lastFrame = false;
while (!lastFrame) {
int payloadSize = min(fragmentSize, remaining);
lastFrame = payloadSize == remaining;
List<int> frame = createFrame(lastFrame, firstFrame ? opcode : 0x00, null,
message, messageIndex, payloadSize);
frameCount++;
messageIndex += payloadSize;
controller.add(frame);
remaining -= payloadSize;
firstFrame = false;
}
}
void testMessageFragmentation(int opcode, List<int> message) {
mc.expectedMessage = message;
// Test with fragmenting the message in different fragment sizes.
if (message.length <= 10) {
for (int i = 1; i < 10; i++) {
testFragmentMessage(opcode, message, i);
}
} else {
testFragmentMessage(opcode, message, 10);
testFragmentMessage(opcode, message, 100);
}
}
void runTest(int from, int to, int step) {
for (int messageLength = from; messageLength < to; messageLength += step) {
List<int> message = new List<int>(messageLength);
for (int i = 0; i < messageLength; i++) message[i] = i & 0x7F;
testMessageFragmentation(FRAME_OPCODE_TEXT, message);
for (int i = 0; i < messageLength; i++) message[i] = i & 0xFF;
testMessageFragmentation(FRAME_OPCODE_BINARY, message);
}
}
// Test different message sizes.
runTest(0, 10, 1);
runTest(120, 130, 1);
runTest(0, 1000, 100);
runTest(65534, 65537, 1);
print("Fragment messages test, messages $messageCount, frames $frameCount");
Expect.equals(messageCount, mc.messageCount);
}
void testUnmaskedMessage() {
var transformer = new _WebSocketProtocolTransformer(true);
var controller = new StreamController<List<int>>(sync: true);
asyncStart();
controller.stream.transform(transformer).listen((_) {}, onError: (e) {
asyncEnd();
});
var message = new Uint8List(10);
List<int> frame =
createFrame(true, FRAME_OPCODE_BINARY, null, message, 0, message.length);
controller.add(frame);
}
void main() {
testFullMessages();
testFragmentedMessages();
testUnmaskedMessage();
}