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);
   });
 }