From 6d63acfccdec080fafb600ee903d86bdab8aeed7 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Mon, 19 May 2014 19:55:35 +0000 Subject: [PATCH] Support a user-supplied dart:io client in pkg/http. R=jmesserly@google.com BUG=18871 Review URL: https://codereview.chromium.org//299483002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36319 260f80e4-7a28-3924-810f-c04153c831b5 --- pkg/http/CHANGELOG.md | 4 ++++ pkg/http/lib/http.dart | 1 + pkg/http/lib/src/io.dart | 3 +++ pkg/http/lib/src/io_client.dart | 18 +++++++++++++--- pkg/http/pubspec.yaml | 2 +- pkg/http/test/io/client_test.dart | 35 +++++++++++++++++++++++++++++++ 6 files changed, 59 insertions(+), 4 deletions(-) diff --git a/pkg/http/CHANGELOG.md b/pkg/http/CHANGELOG.md index d6fdd445a61..ac6a0cf0054 100644 --- a/pkg/http/CHANGELOG.md +++ b/pkg/http/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.11.1 + +* Expose the `IOClient` class which wraps a `dart:io` `HttpClient`. + ## 0.11.0+1 * Fix a bug in handling errors in decoding XMLHttpRequest responses for diff --git a/pkg/http/lib/http.dart b/pkg/http/lib/http.dart index d93a1a53512..5b9b1f9bb6d 100644 --- a/pkg/http/lib/http.dart +++ b/pkg/http/lib/http.dart @@ -18,6 +18,7 @@ export 'src/base_response.dart'; export 'src/byte_stream.dart'; export 'src/client.dart'; export 'src/exception.dart'; +export 'src/io_client.dart'; export 'src/multipart_file.dart'; export 'src/multipart_request.dart'; export 'src/request.dart'; diff --git a/pkg/http/lib/src/io.dart b/pkg/http/lib/src/io.dart index 1730706331f..767dda054a2 100644 --- a/pkg/http/lib/src/io.dart +++ b/pkg/http/lib/src/io.dart @@ -43,6 +43,9 @@ newFile(String path) => _file.newInstance(const Symbol(''), [path]).reflectee; /// Returns whether [error] is a `dart:io` HttpException. bool isHttpException(error) => reflect(error).type.isSubtypeOf(_httpException); +/// Returns whether [client] is a `dart:io` HttpClient. +bool isHttpClient(client) => reflect(client).type.isSubtypeOf(_httpClient); + /// Tries to load `dart:io` and returns `null` if it fails. LibraryMirror _getLibrary() { try { diff --git a/pkg/http/lib/src/io_client.dart b/pkg/http/lib/src/io_client.dart index 9fd81acdfa8..1114180cba7 100644 --- a/pkg/http/lib/src/io_client.dart +++ b/pkg/http/lib/src/io_client.dart @@ -14,15 +14,27 @@ import 'exception.dart'; import 'io.dart' as io; import 'streamed_response.dart'; -/// A `dart:io`-based HTTP client. This is the default client. +/// A `dart:io`-based HTTP client. +/// +/// This is the default client when running on the command line. class IOClient extends BaseClient { /// The underlying `dart:io` HTTP client. var _inner; /// Creates a new HTTP client. - IOClient() { + /// + /// [innerClient] must be a `dart:io` HTTP client. If it's not passed, a + /// default one will be instantiated. + IOClient([innerClient]) { io.assertSupported("IOClient"); - _inner = io.newHttpClient(); + if (innerClient != null) { + // TODO(nweiz): remove this assert when we can type [innerClient] + // properly. + assert(io.isHttpClient(innerClient)); + _inner = innerClient; + } else { + _inner = io.newHttpClient(); + } } /// Sends an HTTP request and asynchronously returns the response. diff --git a/pkg/http/pubspec.yaml b/pkg/http/pubspec.yaml index b02477ec14d..077d277fbaf 100644 --- a/pkg/http/pubspec.yaml +++ b/pkg/http/pubspec.yaml @@ -1,5 +1,5 @@ name: http -version: 0.11.0+1 +version: 0.11.1 author: "Dart Team " homepage: https://pub.dartlang.org/packages/http description: A composable, Future-based API for making HTTP requests. diff --git a/pkg/http/test/io/client_test.dart b/pkg/http/test/io/client_test.dart index b9cc5fa9116..a9d76945c04 100644 --- a/pkg/http/test/io/client_test.dart +++ b/pkg/http/test/io/client_test.dart @@ -48,6 +48,41 @@ void main() { }), completes); }); + test('#send a StreamedRequest with a custom client', () { + expect(startServer().then((_) { + var ioClient = new HttpClient(); + var client = new http.IOClient(ioClient); + var request = new http.StreamedRequest("POST", serverUrl); + request.headers[HttpHeaders.CONTENT_TYPE] = + 'application/json; charset=utf-8'; + request.headers[HttpHeaders.USER_AGENT] = 'Dart'; + + expect(client.send(request).then((response) { + expect(response.request, equals(request)); + expect(response.statusCode, equals(200)); + expect(response.headers['single'], equals('value')); + // dart:io internally normalizes outgoing headers so that they never + // have multiple headers with the same name, so there's no way to test + // whether we handle that case correctly. + + return response.stream.bytesToString(); + }).whenComplete(client.close), completion(parse(equals({ + 'method': 'POST', + 'path': '/', + 'headers': { + 'content-type': ['application/json; charset=utf-8'], + 'accept-encoding': ['gzip'], + 'user-agent': ['Dart'], + 'transfer-encoding': ['chunked'] + }, + 'body': '{"hello": "world"}' + })))); + + request.sink.add('{"hello": "world"}'.codeUnits); + request.sink.close(); + }), completes); + }); + test('#send with an invalid URL', () { expect(startServer().then((_) { var client = new http.Client();