Add browser support for response header tests. (#716)
diff --git a/pkgs/http_client_conformance_tests/lib/src/response_headers_server.dart b/pkgs/http_client_conformance_tests/lib/src/response_headers_server.dart
new file mode 100644
index 0000000..3f2d4d3
--- /dev/null
+++ b/pkgs/http_client_conformance_tests/lib/src/response_headers_server.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2022, 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.
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:async/async.dart';
+import 'package:stream_channel/stream_channel.dart';
+
+/// Starts an HTTP server that returns custom headers.
+///
+/// Channel protocol:
+/// On Startup:
+/// - send port
+/// On Request Received:
+/// - load response header map from channel
+/// - exit
+void hybridMain(StreamChannel<Object?> channel) async {
+ late HttpServer server;
+ final clientQueue = StreamQueue(channel.stream);
+
+ server = (await HttpServer.bind('localhost', 0))
+ ..listen((request) async {
+ request.response.headers.set('Access-Control-Allow-Origin', '*');
+ request.response.headers.set('Access-Control-Expose-Headers', '*');
+
+ (await clientQueue.next as Map).forEach((key, value) => request
+ .response.headers
+ .set(key as String, value as String, preserveHeaderCase: true));
+
+ await request.response.close();
+ unawaited(server.close());
+ });
+
+ channel.sink.add(server.port);
+}
diff --git a/pkgs/http_client_conformance_tests/lib/src/response_headers_tests.dart b/pkgs/http_client_conformance_tests/lib/src/response_headers_tests.dart
index 9ff0ee6..2864bda 100644
--- a/pkgs/http_client_conformance_tests/lib/src/response_headers_tests.dart
+++ b/pkgs/http_client_conformance_tests/lib/src/response_headers_tests.dart
@@ -2,81 +2,57 @@
// 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.
-import 'dart:async';
-import 'dart:io';
-
+import 'package:async/async.dart';
import 'package:http/http.dart';
+import 'package:stream_channel/stream_channel.dart';
import 'package:test/test.dart';
-/// Tests that the [Client] correctly processes response headers e.g.
-/// 'Content-Length'.
+import 'utils.dart';
+
+/// Tests that the [Client] correctly processes response headers.
void testResponseHeaders(Client client) async {
group('server headers', () {
+ late String host;
+ late StreamChannel<Object?> httpServerChannel;
+ late StreamQueue<Object?> httpServerQueue;
+
+ setUp(() async {
+ httpServerChannel = await startServer('response_headers_server.dart');
+ httpServerQueue = StreamQueue(httpServerChannel.stream);
+ host = 'localhost:${await httpServerQueue.next}';
+ });
+
test('single header', () async {
- final server = (await HttpServer.bind('localhost', 0))
- ..listen((request) async {
- await request.drain<void>();
- var response = request.response;
- response.headers.set('foo', 'bar');
- unawaited(response.close());
- });
- final response =
- await client.get(Uri.http('localhost:${server.port}', ''));
+ httpServerChannel.sink.add({'foo': 'bar'});
+
+ final response = await client.get(Uri.http(host, ''));
expect(response.headers['foo'], 'bar');
- await server.close();
});
test('UPPERCASE header', () async {
- final server = (await HttpServer.bind('localhost', 0))
- ..listen((request) async {
- await request.drain<void>();
- var response = request.response;
- response.headers.set('FOO', 'BAR', preserveHeaderCase: true);
- unawaited(response.close());
- });
+ httpServerChannel.sink.add({'foo': 'BAR'});
+
+ final response = await client.get(Uri.http(host, ''));
// RFC 2616 14.44 states that header field names are case-insensive.
// http.Client canonicalizes field names into lower case.
- final response =
- await client.get(Uri.http('localhost:${server.port}', ''));
expect(response.headers['foo'], 'BAR');
- await server.close();
});
test('multiple headers', () async {
- final server = (await HttpServer.bind('localhost', 0))
- ..listen((request) async {
- await request.drain<void>();
- var response = request.response;
- response.headers
- ..set('field1', 'value1')
- ..set('field2', 'value2')
- ..set('field3', 'value3');
- unawaited(response.close());
- });
- final response =
- await client.get(Uri.http('localhost:${server.port}', ''));
+ httpServerChannel.sink
+ .add({'field1': 'value1', 'field2': 'value2', 'field3': 'value3'});
+
+ final response = await client.get(Uri.http(host, ''));
expect(response.headers['field1'], 'value1');
expect(response.headers['field2'], 'value2');
expect(response.headers['field3'], 'value3');
- await server.close();
});
test('multiple values per header', () async {
- final server = (await HttpServer.bind('localhost', 0))
- ..listen((request) async {
- await request.drain<void>();
- var response = request.response;
- // RFC 2616 14.44 states that header field names are case-insensive.
- response.headers
- ..add('list', 'apple')
- ..add('list', 'orange')
- ..add('List', 'banana');
- unawaited(response.close());
- });
- final response =
- await client.get(Uri.http('localhost:${server.port}', ''));
+ httpServerChannel.sink.add({'list': 'apple, orange, banana'});
+
+ final response = await client.get(Uri.http(host, ''));
expect(response.headers['list'], 'apple, orange, banana');
- await server.close();
});
});
}
diff --git a/pkgs/http_client_conformance_tests/test/browser_client_test.dart b/pkgs/http_client_conformance_tests/test/browser_client_test.dart
index 496b190..cbc484b 100644
--- a/pkgs/http_client_conformance_tests/test/browser_client_test.dart
+++ b/pkgs/http_client_conformance_tests/test/browser_client_test.dart
@@ -12,12 +12,9 @@
final client = BrowserClient();
group('testAll', () {
- // TODO: Replace this with `testAll` when all tests support browser testing.
- testRequestBody(client);
- testRedirect(client, redirectAlwaysAllowed: true);
- testRequestBodyStreamed(client, canStreamRequestBody: false);
- testResponseBody(client, canStreamResponseBody: false);
- testResponseBodyStreamed(client, canStreamResponseBody: false);
- testRequestHeaders(client);
+ testAll(client,
+ redirectAlwaysAllowed: true,
+ canStreamRequestBody: false,
+ canStreamResponseBody: false);
});
}