Farewell, local fork of the http package. (#8642)

diff --git a/examples/stocks/lib/stock_data.dart b/examples/stocks/lib/stock_data.dart
index 7ab4c65..cd82d8b 100644
--- a/examples/stocks/lib/stock_data.dart
+++ b/examples/stocks/lib/stock_data.dart
@@ -10,7 +10,8 @@
 import 'dart:convert';
 import 'dart:math' as math;
 
-import 'package:flutter/http.dart' as http;
+import 'package:flutter/services.dart';
+import 'package:http/http.dart' as http;
 
 final math.Random _rng = new math.Random();
 
@@ -60,19 +61,22 @@
 }
 
 class StockDataFetcher {
-  int _nextChunk = 0;
+  StockDataFetcher(this.callback) {
+    _httpClient = createHttpClient();
+    _fetchNextChunk();
+  }
+
   final StockDataCallback callback;
+  http.Client _httpClient;
 
   static bool actuallyFetchData = true;
 
-  StockDataFetcher(this.callback) {
-    _fetchNextChunk();
-  }
+  int _nextChunk = 0;
 
   void _fetchNextChunk() {
     if (!actuallyFetchData)
       return;
-    http.get(_urlToFetch(_nextChunk++)).then<Null>((http.Response response) {
+    _httpClient.get(_urlToFetch(_nextChunk++)).then<Null>((http.Response response) {
       final String json = response.body;
       if (json == null) {
         print("Failed to load stock data chunk ${_nextChunk - 1}");
diff --git a/examples/stocks/pubspec.yaml b/examples/stocks/pubspec.yaml
index 07fb30f..f15f87d 100644
--- a/examples/stocks/pubspec.yaml
+++ b/examples/stocks/pubspec.yaml
@@ -3,6 +3,7 @@
   flutter:
     sdk: flutter
   intl: '>=0.14.0 <0.15.0'
+  http: '>=0.11.3+11'
 
 dev_dependencies:
   flutter_test:
diff --git a/packages/flutter/lib/http.dart b/packages/flutter/lib/http.dart
deleted file mode 100644
index b0240bc..0000000
--- a/packages/flutter/lib/http.dart
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/// A [Future]-based library for making HTTP requests.
-///
-/// To use, import `package:flutter/http.dart`.
-///
-/// This library is based on Dart's `http` package, but differs in that it does
-/// not have a dependency on mirrors.
-///
-// TODO(chinmaygarde): The contents of `lib/src/http` will become redundant
-// once https://github.com/dart-lang/http/issues/1 is fixed (removes the use
-// of mirrors). Once that issue is addressed, we should get rid this directory
-// and use `dart-lang/http` directly.
-library http;
-
-export 'src/http/http.dart';
-export 'src/http/mock_client.dart';
-export 'src/http/response.dart';
diff --git a/packages/flutter/lib/services.dart b/packages/flutter/lib/services.dart
index 4c34210..cbbbefe 100644
--- a/packages/flutter/lib/services.dart
+++ b/packages/flutter/lib/services.dart
@@ -13,14 +13,15 @@
 export 'src/services/asset_bundle.dart';
 export 'src/services/binding.dart';
 export 'src/services/clipboard.dart';
-export 'src/services/message_codec.dart';
-export 'src/services/message_codecs.dart';
 export 'src/services/haptic_feedback.dart';
+export 'src/services/http_client.dart';
 export 'src/services/image_cache.dart';
 export 'src/services/image_decoder.dart';
 export 'src/services/image_provider.dart';
 export 'src/services/image_resolution.dart';
 export 'src/services/image_stream.dart';
+export 'src/services/message_codec.dart';
+export 'src/services/message_codecs.dart';
 export 'src/services/path_provider.dart';
 export 'src/services/platform_channel.dart';
 export 'src/services/platform_messages.dart';
diff --git a/packages/flutter/lib/src/http/.dartignore b/packages/flutter/lib/src/http/.dartignore
deleted file mode 100644
index e69de29..0000000
--- a/packages/flutter/lib/src/http/.dartignore
+++ /dev/null
diff --git a/packages/flutter/lib/src/http/README.md b/packages/flutter/lib/src/http/README.md
deleted file mode 100644
index 1db8904..0000000
--- a/packages/flutter/lib/src/http/README.md
+++ /dev/null
@@ -1,7 +0,0 @@
-`dart-lang/http` without Mirrors
-================================
-
-The contents of this will become redundant once
-https://github.com/dart-lang/http/issues/1 is fixed (removes the use
-of mirrors). Once that issue is addressed, we should get rid this directory
-and use `dart-lang/http` directly.
diff --git a/packages/flutter/lib/src/http/base_client.dart b/packages/flutter/lib/src/http/base_client.dart
deleted file mode 100644
index 1b16c25..0000000
--- a/packages/flutter/lib/src/http/base_client.dart
+++ /dev/null
@@ -1,199 +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.
-
-import 'dart:async';
-import 'dart:convert';
-import 'dart:typed_data';
-
-import 'package:collection/collection.dart';
-
-import 'base_request.dart';
-import 'client.dart';
-import 'exception.dart';
-import 'request.dart';
-import 'response.dart';
-import 'streamed_response.dart';
-
-/// The abstract base class for an HTTP client. This is a mixin-style class;
-/// subclasses only need to implement [send] and maybe [close], and then they
-/// get various convenience methods for free.
-abstract class BaseClient implements Client {
-  /// Sends an HTTP HEAD request with the given headers to the given URL, which
-  /// can be a [Uri] or a [String].
-  ///
-  /// For more fine-grained control over the request, use [send] instead.
-  @override
-  Future<Response> head(dynamic url, {Map<String, String> headers}) =>
-    _sendUnstreamed("HEAD", url, headers);
-
-  /// Sends an HTTP GET request with the given headers to the given URL, which
-  /// can be a [Uri] or a [String].
-  ///
-  /// For more fine-grained control over the request, use [send] instead.
-  @override
-  Future<Response> get(dynamic url, {Map<String, String> headers}) =>
-    _sendUnstreamed("GET", url, headers);
-
-  /// Sends an HTTP POST request with the given headers and body to the given
-  /// URL, which can be a [Uri] or a [String].
-  ///
-  /// [body] sets the body of the request. It can be a [String], a [List<int>]
-  /// or a [Map<String, String>]. If it's a String, it's encoded using
-  /// [encoding] and used as the body of the request. The content-type of the
-  /// request will default to "text/plain".
-  ///
-  /// If [body] is a List, it's used as a list of bytes for the body of the
-  /// request.
-  ///
-  /// If [body] is a Map, it's encoded as form fields using [encoding]. The
-  /// content-type of the request will be set to
-  /// `"application/x-www-form-urlencoded"`; this cannot be overridden.
-  ///
-  /// [encoding] defaults to UTF-8.
-  ///
-  /// For more fine-grained control over the request, use [send] instead.
-  @override
-  Future<Response> post(dynamic url, {Map<String, String> headers, dynamic body,
-      Encoding encoding}) =>
-    _sendUnstreamed("POST", url, headers, body, encoding);
-
-  /// Sends an HTTP PUT request with the given headers and body to the given
-  /// URL, which can be a [Uri] or a [String].
-  ///
-  /// [body] sets the body of the request. It can be a [String], a [List<int>]
-  /// or a [Map<String, String>]. If it's a String, it's encoded using
-  /// [encoding] and used as the body of the request. The content-type of the
-  /// request will default to "text/plain".
-  ///
-  /// If [body] is a List, it's used as a list of bytes for the body of the
-  /// request.
-  ///
-  /// If [body] is a Map, it's encoded as form fields using [encoding]. The
-  /// content-type of the request will be set to
-  /// `"application/x-www-form-urlencoded"`; this cannot be overridden.
-  ///
-  /// [encoding] defaults to UTF-8.
-  ///
-  /// For more fine-grained control over the request, use [send] instead.
-  @override
-  Future<Response> put(dynamic url, {Map<String, String> headers, dynamic body,
-      Encoding encoding}) =>
-    _sendUnstreamed("PUT", url, headers, body, encoding);
-
-  /// Sends an HTTP PATCH request with the given headers and body to the given
-  /// URL, which can be a [Uri] or a [String].
-  ///
-  /// [body] sets the body of the request. It can be a [String], a [List<int>]
-  /// or a [Map<String, String>]. If it's a String, it's encoded using
-  /// [encoding] and used as the body of the request. The content-type of the
-  /// request will default to "text/plain".
-  ///
-  /// If [body] is a List, it's used as a list of bytes for the body of the
-  /// request.
-  ///
-  /// If [body] is a Map, it's encoded as form fields using [encoding]. The
-  /// content-type of the request will be set to
-  /// `"application/x-www-form-urlencoded"`; this cannot be overridden.
-  ///
-  /// [encoding] defaults to UTF-8.
-  ///
-  /// For more fine-grained control over the request, use [send] instead.
-  @override
-  Future<Response> patch(dynamic url, {Map<String, String> headers, dynamic body,
-      Encoding encoding}) =>
-    _sendUnstreamed("PATCH", url, headers, body, encoding);
-
-  /// Sends an HTTP DELETE request with the given headers to the given URL,
-  /// which can be a [Uri] or a [String].
-  ///
-  /// For more fine-grained control over the request, use [send] instead.
-  @override
-  Future<Response> delete(dynamic url, {Map<String, String> headers}) =>
-    _sendUnstreamed("DELETE", url, headers);
-
-  /// Sends an HTTP GET request with the given headers to the given URL, which
-  /// can be a [Uri] or a [String], and returns a Future that completes to the
-  /// body of the response as a String.
-  ///
-  /// The Future will emit a [ClientException] if the response doesn't have a
-  /// success status code.
-  ///
-  /// For more fine-grained control over the request and response, use [send] or
-  /// [get] instead.
-  @override
-  Future<String> read(dynamic url, {Map<String, String> headers}) {
-    return get(url, headers: headers).then((Response response) {
-      _checkResponseSuccess(url, response);
-      return response.body;
-    });
-  }
-
-  /// Sends an HTTP GET request with the given headers to the given URL, which
-  /// can be a [Uri] or a [String], and returns a Future that completes to the
-  /// body of the response as a list of bytes.
-  ///
-  /// The Future will emit an [ClientException] if the response doesn't have a
-  /// success status code.
-  ///
-  /// For more fine-grained control over the request and response, use [send] or
-  /// [get] instead.
-  @override
-  Future<Uint8List> readBytes(dynamic url, {Map<String, String> headers}) {
-    return get(url, headers: headers).then((Response response) {
-      _checkResponseSuccess(url, response);
-      return response.bodyBytes;
-    });
-  }
-
-  /// Sends an HTTP request and asynchronously returns the response.
-  ///
-  /// Implementers should call [BaseRequest.finalize] to get the body of the
-  /// request as a [ByteStream]. They shouldn't make any assumptions about the
-  /// state of the stream; it could have data written to it asynchronously at a
-  /// later point, or it could already be closed when it's returned. Any
-  /// internal HTTP errors should be wrapped as [ClientException]s.
-  @override
-  Future<StreamedResponse> send(BaseRequest request);
-
-  /// Sends a non-streaming [Request] and returns a non-streaming [Response].
-  Future<Response> _sendUnstreamed(String method, dynamic url,
-      Map<String, String> headers, [dynamic body, Encoding encoding]) async {
-
-    if (url is String) url = Uri.parse(url);
-    Request request = new Request(method, url);
-
-    if (headers != null) request.headers.addAll(headers);
-    if (encoding != null) request.encoding = encoding;
-    if (body != null) {
-      if (body is String) {
-        request.body = body;
-      } else if (body is List) {
-        request.bodyBytes = DelegatingList.typed(body);
-      } else if (body is Map) {
-        request.bodyFields = DelegatingMap.typed(body);
-      } else {
-        throw new ArgumentError('Invalid request body "$body".');
-      }
-    }
-
-    return Response.fromStream(await send(request));
-  }
-
-  /// Throws an error if [response] is not successful.
-  void _checkResponseSuccess(dynamic url, Response response) {
-    if (response.statusCode < 400) return;
-    String message = "Request to $url failed with status ${response.statusCode}";
-    if (response.reasonPhrase != null) {
-      message = "$message: ${response.reasonPhrase}";
-    }
-    if (url is String) url = Uri.parse(url);
-    throw new ClientException("$message.", url);
-  }
-
-  /// Closes the client and cleans up any resources associated with it. It's
-  /// important to close each client when it's done being used; failing to do so
-  /// can cause the Dart process to hang.
-  @override
-  void close() {}
-}
diff --git a/packages/flutter/lib/src/http/base_request.dart b/packages/flutter/lib/src/http/base_request.dart
deleted file mode 100644
index 4af1673..0000000
--- a/packages/flutter/lib/src/http/base_request.dart
+++ /dev/null
@@ -1,141 +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.
-
-import 'dart:async';
-import 'dart:collection';
-
-import 'byte_stream.dart';
-import 'client.dart';
-import 'streamed_response.dart';
-import 'utils.dart';
-
-/// The base class for HTTP requests.
-///
-/// Subclasses of [BaseRequest] can be constructed manually and passed to
-/// [BaseClient.send], which allows the user to provide fine-grained control
-/// over the request properties. However, usually it's easier to use convenience
-/// methods like [get] or [BaseClient.get].
-abstract class BaseRequest {
-  /// The HTTP method of the request. Most commonly "GET" or "POST", less
-  /// commonly "HEAD", "PUT", or "DELETE". Non-standard method names are also
-  /// supported.
-  final String method;
-
-  /// The URL to which the request will be sent.
-  final Uri url;
-
-  /// Creates a new HTTP request.
-  BaseRequest(this.method, this.url)
-    : headers = new LinkedHashMap<String, String>(
-        equals: (String key1, String key2) => key1.toLowerCase() == key2.toLowerCase(),
-        hashCode: (String key) => key.toLowerCase().hashCode);
-
-  /// The size of the request body, in bytes.
-  ///
-  /// This defaults to `null`, which indicates that the size of the request is
-  /// not known in advance.
-  int get contentLength => _contentLength;
-  int _contentLength;
-
-  set contentLength(int value) {
-    if (value != null && value < 0) {
-      throw new ArgumentError("Invalid content length $value.");
-    }
-    _checkFinalized();
-    _contentLength = value;
-  }
-
-  /// Whether a persistent connection should be maintained with the server.
-  /// Defaults to true.
-  bool get persistentConnection => _persistentConnection;
-  bool _persistentConnection = true;
-
-  set persistentConnection(bool value) {
-    _checkFinalized();
-    _persistentConnection = value;
-  }
-
-  /// Whether the client should follow redirects while resolving this request.
-  /// Defaults to true.
-  bool get followRedirects => _followRedirects;
-  bool _followRedirects = true;
-
-  set followRedirects(bool value) {
-    _checkFinalized();
-    _followRedirects = value;
-  }
-
-  /// The maximum number of redirects to follow when [followRedirects] is true.
-  /// If this number is exceeded the [BaseResponse] future will signal a
-  /// [RedirectException]. Defaults to 5.
-  int get maxRedirects => _maxRedirects;
-  int _maxRedirects = 5;
-
-  set maxRedirects(int value) {
-    _checkFinalized();
-    _maxRedirects = value;
-  }
-
-  // TODO(nweiz): automatically parse cookies from headers
-
-  // TODO(nweiz): make this a HttpHeaders object
-  /// The headers for this request.
-  final Map<String, String> headers;
-
-  /// Whether the request has been finalized.
-  bool get finalized => _finalized;
-  bool _finalized = false;
-
-  /// Finalizes the HTTP request in preparation for it being sent. This freezes
-  /// all mutable fields and returns a single-subscription [ByteStream] that
-  /// emits the body of the request.
-  ///
-  /// The base implementation of this returns null rather than a [ByteStream];
-  /// subclasses are responsible for creating the return value, which should be
-  /// single-subscription to ensure that no data is dropped. They should also
-  /// freeze any additional mutable fields they add that don't make sense to
-  /// change after the request headers are sent.
-  ByteStream finalize() {
-    // TODO(nweiz): freeze headers
-    if (finalized) throw new StateError("Can't finalize a finalized Request.");
-    _finalized = true;
-    return null;
-  }
-
-  /// Sends this request.
-  ///
-  /// This automatically initializes a new [Client] and closes that client once
-  /// the request is complete. If you're planning on making multiple requests to
-  /// the same server, you should use a single [Client] for all of those
-  /// requests.
-  Future<StreamedResponse> send() async {
-    Client client = new Client();
-
-    try {
-      StreamedResponse response = await client.send(this);
-      Stream<dynamic> stream = onDone(response.stream, client.close);
-      return new StreamedResponse(
-          new ByteStream(stream),
-          response.statusCode,
-          contentLength: response.contentLength,
-          request: response.request,
-          headers: response.headers,
-          isRedirect: response.isRedirect,
-          persistentConnection: response.persistentConnection,
-          reasonPhrase: response.reasonPhrase);
-    } catch (ex) {
-      client.close();
-      rethrow;
-    }
-  }
-
-  // Throws an error if this request has been finalized.
-  void _checkFinalized() {
-    if (!finalized) return;
-    throw new StateError("Can't modify a finalized Request.");
-  }
-
-  @override
-  String toString() => "$method $url";
-}
diff --git a/packages/flutter/lib/src/http/base_response.dart b/packages/flutter/lib/src/http/base_response.dart
deleted file mode 100644
index 148b751..0000000
--- a/packages/flutter/lib/src/http/base_response.dart
+++ /dev/null
@@ -1,53 +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.
-
-import 'base_request.dart';
-
-/// The base class for HTTP responses.
-///
-/// Subclasses of [BaseResponse] are usually not constructed manually; instead,
-/// they're returned by [BaseClient.send] or other HTTP client methods.
-abstract class BaseResponse {
-  /// The (frozen) request that triggered this response.
-  final BaseRequest request;
-
-  /// The status code of the response.
-  final int statusCode;
-
-  /// The reason phrase associated with the status code.
-  final String reasonPhrase;
-
-  /// The size of the response body, in bytes.
-  ///
-  /// If the size of the request is not known in advance, this is `null`.
-  final int contentLength;
-
-  // TODO(nweiz): automatically parse cookies from headers
-
-  // TODO(nweiz): make this a HttpHeaders object.
-  /// The headers for this response.
-  final Map<String, String> headers;
-
-  /// Whether this response is a redirect.
-  final bool isRedirect;
-
-  /// Whether the server requested that a persistent connection be maintained.
-  final bool persistentConnection;
-
-  /// Creates a new HTTP response.
-  BaseResponse(
-      this.statusCode,
-      {this.contentLength,
-       this.request,
-       this.headers: const <String, String>{},
-       this.isRedirect: false,
-       this.persistentConnection: true,
-       this.reasonPhrase}) {
-    if (statusCode < 100) {
-      throw new ArgumentError("Invalid status code $statusCode.");
-    } else if (contentLength != null && contentLength < 0) {
-      throw new ArgumentError("Invalid content length $contentLength.");
-    }
-  }
-}
diff --git a/packages/flutter/lib/src/http/byte_stream.dart b/packages/flutter/lib/src/http/byte_stream.dart
deleted file mode 100644
index 825d419..0000000
--- a/packages/flutter/lib/src/http/byte_stream.dart
+++ /dev/null
@@ -1,36 +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.
-
-import 'dart:async';
-import 'dart:convert';
-import 'dart:typed_data';
-
-/// A stream of chunks of bytes representing a single piece of data.
-class ByteStream extends StreamView<List<int>> {
-  ByteStream(Stream<List<int>> stream)
-      : super(stream);
-
-  /// Returns a single-subscription byte stream that will emit the given bytes
-  /// in a single chunk.
-  factory ByteStream.fromBytes(List<int> bytes) =>
-      new ByteStream(new Stream<dynamic>.fromIterable(<List<int>>[bytes]));
-
-  /// Collects the data of this stream in a [Uint8List].
-  Future<Uint8List> toBytes() {
-    Completer<Uint8List> completer = new Completer<Uint8List>();
-    dynamic sink = new ByteConversionSink.withCallback((dynamic bytes) =>
-        completer.complete(new Uint8List.fromList(bytes)));
-    listen(sink.add, onError: completer.completeError, onDone: sink.close,
-        cancelOnError: true);
-    return completer.future;
-  }
-
-  /// Collect the data of this stream in a [String], decoded according to
-  /// [encoding], which defaults to `UTF8`.
-  Future<String> bytesToString([Encoding encoding=UTF8]) =>
-      encoding.decodeStream(this);
-
-  Stream<String> toStringStream([Encoding encoding=UTF8]) =>
-      encoding.decoder.bind(this);
-}
diff --git a/packages/flutter/lib/src/http/client.dart b/packages/flutter/lib/src/http/client.dart
deleted file mode 100644
index 3280777..0000000
--- a/packages/flutter/lib/src/http/client.dart
+++ /dev/null
@@ -1,148 +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.
-
-import 'dart:async';
-import 'dart:convert';
-import 'dart:typed_data';
-
-import 'base_client.dart';
-import 'base_request.dart';
-import 'io_client.dart';
-import 'response.dart';
-import 'streamed_response.dart';
-
-typedef Client ClientOverride();
-
-/// The interface for HTTP clients that take care of maintaining persistent
-/// connections across multiple requests to the same server. If you only need to
-/// send a single request, it's usually easier to use [head], [get], [post],
-/// [put], [patch], or [delete] instead.
-///
-/// When creating an HTTP client class with additional functionality, you must
-/// extend [BaseClient] rather than [Client]. In most cases, you can wrap
-/// another instance of [Client] and add functionality on top of that. This
-/// allows all classes implementing [Client] to be mutually composable.
-abstract class Client {
-  /// Creates a new client.
-  ///
-  /// Currently this will create an [IOClient] if `dart:io` is available and
-  /// throw an [UnsupportedError] otherwise. In the future, it will create a
-  /// [BrowserClient] if `dart:html` is available.
-  factory Client() {
-    return clientOverride == null ? new IOClient() : clientOverride();
-  }
-
-  static ClientOverride clientOverride;
-
-  /// Sends an HTTP HEAD request with the given headers to the given URL, which
-  /// can be a [Uri] or a [String].
-  ///
-  /// For more fine-grained control over the request, use [send] instead.
-  Future<Response> head(dynamic url, {Map<String, String> headers});
-
-  /// Sends an HTTP GET request with the given headers to the given URL, which
-  /// can be a [Uri] or a [String].
-  ///
-  /// For more fine-grained control over the request, use [send] instead.
-  Future<Response> get(dynamic url, {Map<String, String> headers});
-
-  /// Sends an HTTP POST request with the given headers and body to the given
-  /// URL, which can be a [Uri] or a [String].
-  ///
-  /// [body] sets the body of the request. It can be a [String], a [List<int>]
-  /// or a [Map<String, String>]. If it's a String, it's encoded using
-  /// [encoding] and used as the body of the request. The content-type of the
-  /// request will default to "text/plain".
-  ///
-  /// If [body] is a List, it's used as a list of bytes for the body of the
-  /// request.
-  ///
-  /// If [body] is a Map, it's encoded as form fields using [encoding]. The
-  /// content-type of the request will be set to
-  /// `"application/x-www-form-urlencoded"`; this cannot be overridden.
-  ///
-  /// [encoding] defaults to [UTF8].
-  ///
-  /// For more fine-grained control over the request, use [send] instead.
-  Future<Response> post(dynamic url, {Map<String, String> headers, dynamic body,
-      Encoding encoding});
-
-  /// Sends an HTTP PUT request with the given headers and body to the given
-  /// URL, which can be a [Uri] or a [String].
-  ///
-  /// [body] sets the body of the request. It can be a [String], a [List<int>]
-  /// or a [Map<String, String>]. If it's a String, it's encoded using
-  /// [encoding] and used as the body of the request. The content-type of the
-  /// request will default to "text/plain".
-  ///
-  /// If [body] is a List, it's used as a list of bytes for the body of the
-  /// request.
-  ///
-  /// If [body] is a Map, it's encoded as form fields using [encoding]. The
-  /// content-type of the request will be set to
-  /// `"application/x-www-form-urlencoded"`; this cannot be overridden.
-  ///
-  /// [encoding] defaults to [UTF8].
-  ///
-  /// For more fine-grained control over the request, use [send] instead.
-  Future<Response> put(dynamic url, {Map<String, String> headers, dynamic body,
-      Encoding encoding});
-
-  /// Sends an HTTP PATCH request with the given headers and body to the given
-  /// URL, which can be a [Uri] or a [String].
-  ///
-  /// [body] sets the body of the request. It can be a [String], a [List<int>]
-  /// or a [Map<String, String>]. If it's a String, it's encoded using
-  /// [encoding] and used as the body of the request. The content-type of the
-  /// request will default to "text/plain".
-  ///
-  /// If [body] is a List, it's used as a list of bytes for the body of the
-  /// request.
-  ///
-  /// If [body] is a Map, it's encoded as form fields using [encoding]. The
-  /// content-type of the request will be set to
-  /// `"application/x-www-form-urlencoded"`; this cannot be overridden.
-  ///
-  /// [encoding] defaults to [UTF8].
-  ///
-  /// For more fine-grained control over the request, use [send] instead.
-  Future<Response> patch(dynamic url, {Map<String, String> headers, dynamic body,
-      Encoding encoding});
-
-  /// Sends an HTTP DELETE request with the given headers to the given URL,
-  /// which can be a [Uri] or a [String].
-  ///
-  /// For more fine-grained control over the request, use [send] instead.
-  Future<Response> delete(dynamic url, {Map<String, String> headers});
-
-  /// Sends an HTTP GET request with the given headers to the given URL, which
-  /// can be a [Uri] or a [String], and returns a Future that completes to the
-  /// body of the response as a String.
-  ///
-  /// The Future will emit a [ClientException] if the response doesn't have a
-  /// success status code.
-  ///
-  /// For more fine-grained control over the request and response, use [send] or
-  /// [get] instead.
-  Future<String> read(dynamic url, {Map<String, String> headers});
-
-  /// Sends an HTTP GET request with the given headers to the given URL, which
-  /// can be a [Uri] or a [String], and returns a Future that completes to the
-  /// body of the response as a list of bytes.
-  ///
-  /// The Future will emit a [ClientException] if the response doesn't have a
-  /// success status code.
-  ///
-  /// For more fine-grained control over the request and response, use [send] or
-  /// [get] instead.
-  Future<Uint8List> readBytes(dynamic url, {Map<String, String> headers});
-
-  /// Sends an HTTP request and asynchronously returns the response.
-  Future<StreamedResponse> send(BaseRequest request);
-
-  /// Closes the client and cleans up any resources associated with it. It's
-  /// important to close each client when it's done being used; failing to do so
-  /// can cause the Dart process to hang.
-  void close();
-}
diff --git a/packages/flutter/lib/src/http/exception.dart b/packages/flutter/lib/src/http/exception.dart
deleted file mode 100644
index c92a861..0000000
--- a/packages/flutter/lib/src/http/exception.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2014, 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.
-
-/// An exception caused by an error in a pkg/http client.
-class ClientException implements Exception {
-  final String message;
-
-  /// The URL of the HTTP request or response that failed.
-  final Uri uri;
-
-  ClientException(this.message, [this.uri]);
-
-  @override
-  String toString() => message;
-}
diff --git a/packages/flutter/lib/src/http/http.dart b/packages/flutter/lib/src/http/http.dart
deleted file mode 100644
index 6806075..0000000
--- a/packages/flutter/lib/src/http/http.dart
+++ /dev/null
@@ -1,171 +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.
-
-/// A composable, [Future]-based library for making HTTP requests.
-import 'dart:async';
-import 'dart:convert';
-import 'dart:typed_data';
-
-import 'client.dart';
-import 'response.dart';
-
-export 'base_client.dart';
-export 'base_request.dart';
-export 'base_response.dart';
-export 'byte_stream.dart';
-export 'client.dart';
-export 'exception.dart';
-export 'io_client.dart';
-export 'multipart_file.dart';
-export 'multipart_request.dart';
-export 'request.dart';
-export 'response.dart';
-export 'streamed_request.dart';
-export 'streamed_response.dart';
-
-/// Sends an HTTP HEAD request with the given headers to the given URL, which
-/// can be a [Uri] or a [String].
-///
-/// This automatically initializes a new [Client] and closes that client once
-/// the request is complete. If you're planning on making multiple requests to
-/// the same server, you should use a single [Client] for all of those requests.
-///
-/// For more fine-grained control over the request, use [Request] instead.
-Future<Response> head(dynamic url, {Map<String, String> headers}) =>
-  _withClient((Client client) => client.head(url, headers: headers));
-
-/// Sends an HTTP GET request with the given headers to the given URL, which can
-/// be a [Uri] or a [String].
-///
-/// This automatically initializes a new [Client] and closes that client once
-/// the request is complete. If you're planning on making multiple requests to
-/// the same server, you should use a single [Client] for all of those requests.
-///
-/// For more fine-grained control over the request, use [Request] instead.
-Future<Response> get(dynamic url, {Map<String, String> headers}) =>
-  _withClient((Client client) => client.get(url, headers: headers));
-
-/// Sends an HTTP POST request with the given headers and body to the given URL,
-/// which can be a [Uri] or a [String].
-///
-/// [body] sets the body of the request. It can be a [String], a [List<int>] or
-/// a [Map<String, String>]. If it's a String, it's encoded using [encoding] and
-/// used as the body of the request. The content-type of the request will
-/// default to "text/plain".
-///
-/// If [body] is a List, it's used as a list of bytes for the body of the
-/// request.
-///
-/// If [body] is a Map, it's encoded as form fields using [encoding]. The
-/// content-type of the request will be set to
-/// `"application/x-www-form-urlencoded"`; this cannot be overridden.
-///
-/// [encoding] defaults to [UTF8].
-///
-/// For more fine-grained control over the request, use [Request] or
-/// [StreamedRequest] instead.
-Future<Response> post(dynamic url, {Map<String, String> headers, dynamic body,
-    Encoding encoding}) =>
-  _withClient((Client client) => client.post(url,
-      headers: headers, body: body, encoding: encoding));
-
-/// Sends an HTTP PUT request with the given headers and body to the given URL,
-/// which can be a [Uri] or a [String].
-///
-/// [body] sets the body of the request. It can be a [String], a [List<int>] or
-/// a [Map<String, String>]. If it's a String, it's encoded using [encoding] and
-/// used as the body of the request. The content-type of the request will
-/// default to "text/plain".
-///
-/// If [body] is a List, it's used as a list of bytes for the body of the
-/// request.
-///
-/// If [body] is a Map, it's encoded as form fields using [encoding]. The
-/// content-type of the request will be set to
-/// `"application/x-www-form-urlencoded"`; this cannot be overridden.
-///
-/// [encoding] defaults to [UTF8].
-///
-/// For more fine-grained control over the request, use [Request] or
-/// [StreamedRequest] instead.
-Future<Response> put(dynamic url, {Map<String, String> headers, dynamic body,
-    Encoding encoding}) =>
-  _withClient((Client client) => client.put(url,
-      headers: headers, body: body, encoding: encoding));
-
-/// Sends an HTTP PATCH request with the given headers and body to the given
-/// URL, which can be a [Uri] or a [String].
-///
-/// [body] sets the body of the request. It can be a [String], a [List<int>] or
-/// a [Map<String, String>]. If it's a String, it's encoded using [encoding] and
-/// used as the body of the request. The content-type of the request will
-/// default to "text/plain".
-///
-/// If [body] is a List, it's used as a list of bytes for the body of the
-/// request.
-///
-/// If [body] is a Map, it's encoded as form fields using [encoding]. The
-/// content-type of the request will be set to
-/// `"application/x-www-form-urlencoded"`; this cannot be overridden.
-///
-/// [encoding] defaults to [UTF8].
-///
-/// For more fine-grained control over the request, use [Request] or
-/// [StreamedRequest] instead.
-Future<Response> patch(dynamic url, {Map<String, String> headers, dynamic body,
-    Encoding encoding}) =>
-  _withClient((Client client) => client.patch(url,
-      headers: headers, body: body, encoding: encoding));
-
-/// Sends an HTTP DELETE request with the given headers to the given URL, which
-/// can be a [Uri] or a [String].
-///
-/// This automatically initializes a new [Client] and closes that client once
-/// the request is complete. If you're planning on making multiple requests to
-/// the same server, you should use a single [Client] for all of those requests.
-///
-/// For more fine-grained control over the request, use [Request] instead.
-Future<Response> delete(dynamic url, {Map<String, String> headers}) =>
-  _withClient((Client client) => client.delete(url, headers: headers));
-
-/// Sends an HTTP GET request with the given headers to the given URL, which can
-/// be a [Uri] or a [String], and returns a Future that completes to the body of
-/// the response as a [String].
-///
-/// The Future will emit a [ClientException] if the response doesn't have a
-/// success status code.
-///
-/// This automatically initializes a new [Client] and closes that client once
-/// the request is complete. If you're planning on making multiple requests to
-/// the same server, you should use a single [Client] for all of those requests.
-///
-/// For more fine-grained control over the request and response, use [Request]
-/// instead.
-Future<String> read(dynamic url, {Map<String, String> headers}) =>
-  _withClient((Client client) => client.read(url, headers: headers));
-
-/// Sends an HTTP GET request with the given headers to the given URL, which can
-/// be a [Uri] or a [String], and returns a Future that completes to the body of
-/// the response as a list of bytes.
-///
-/// The Future will emit a [ClientException] if the response doesn't have a
-/// success status code.
-///
-/// This automatically initializes a new [Client] and closes that client once
-/// the request is complete. If you're planning on making multiple requests to
-/// the same server, you should use a single [Client] for all of those requests.
-///
-/// For more fine-grained control over the request and response, use [Request]
-/// instead.
-Future<Uint8List> readBytes(dynamic url, {Map<String, String> headers}) =>
-  _withClient((Client client) => client.readBytes(url, headers: headers));
-
-Future/*<T>*/ _withClient/*<T>*/(Future/*<T>*/ fn(Client client)) async {
-  Client client = new Client();
-  try {
-    return await fn(client);
-  } finally {
-    client.close();
-  }
-}
diff --git a/packages/flutter/lib/src/http/io.dart b/packages/flutter/lib/src/http/io.dart
deleted file mode 100644
index 7748a6d..0000000
--- a/packages/flutter/lib/src/http/io.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2014, 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:io' as io;
-
-/// Whether `dart:io` is supported on this platform.
-bool get supported => true;
-
-/// Asserts that the [name]d `dart:io` feature is supported on this platform.
-///
-/// If `dart:io` doesn't work on this platform, this throws an
-/// [UnsupportedError].
-void assertSupported(String name) {}
-
-/// Creates a new `dart:io` HttpClient instance.
-io.HttpClient newHttpClient() => new io.HttpClient();
-
-/// Creates a new `dart:io` File instance with the given [path].
-io.File newFile(String path) => new io.File(path);
-
-/// Returns whether [error] is a `dart:io` HttpException.
-bool isHttpException(dynamic error) => error is io.HttpException;
-
-/// Returns whether [client] is a `dart:io` HttpClient.
-bool isHttpClient(dynamic client) => client is io.HttpClient;
diff --git a/packages/flutter/lib/src/http/io_client.dart b/packages/flutter/lib/src/http/io_client.dart
deleted file mode 100644
index 5a3ae79..0000000
--- a/packages/flutter/lib/src/http/io_client.dart
+++ /dev/null
@@ -1,90 +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.
-
-import 'dart:async';
-
-import 'package:async/async.dart';
-
-import 'base_client.dart';
-import 'base_request.dart';
-import 'exception.dart';
-import 'io.dart' as io;
-import 'streamed_response.dart';
-
-/// 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.
-  dynamic _inner;
-
-  /// Creates a new HTTP client.
-  ///
-  /// [innerClient] must be a `dart:io` HTTP client. If it's not passed, a
-  /// default one will be instantiated.
-  IOClient([dynamic innerClient]) {
-    io.assertSupported("IOClient");
-    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.
-  @override
-  Future<StreamedResponse> send(BaseRequest request) async {
-    dynamic stream = request.finalize();
-
-    try {
-      dynamic ioRequest = await _inner.openUrl(request.method, request.url);
-
-      ioRequest
-          ..followRedirects = request.followRedirects
-          ..maxRedirects = request.maxRedirects
-          ..contentLength = request.contentLength == null
-              ? -1
-              : request.contentLength
-          ..persistentConnection = request.persistentConnection;
-      request.headers.forEach((String name, String value) {
-        ioRequest.headers.set(name, value);
-      });
-
-      dynamic response = await stream.pipe(
-          DelegatingStreamConsumer.typed(ioRequest));
-      Map<String, dynamic> headers = <String, dynamic>{};
-      response.headers.forEach((String key, dynamic values) {
-        headers[key] = values.join(',');
-      });
-
-      return new StreamedResponse(
-          DelegatingStream.typed/*<List<int>>*/(response).handleError((dynamic error) =>
-              throw new ClientException(error.message, error.uri),
-              test: (dynamic error) => io.isHttpException(error)),
-          response.statusCode,
-          contentLength: response.contentLength == -1
-              ? null
-              : response.contentLength,
-          request: request,
-          headers: headers,
-          isRedirect: response.isRedirect,
-          persistentConnection: response.persistentConnection,
-          reasonPhrase: response.reasonPhrase);
-    } catch (error) {
-      if (!io.isHttpException(error)) rethrow;
-      throw new ClientException(error.message, error.uri);
-    }
-  }
-
-  /// Closes the client. This terminates all active connections. If a client
-  /// remains unclosed, the Dart process may not terminate.
-  @override
-  void close() {
-    if (_inner != null) _inner.close(force: true);
-    _inner = null;
-  }
-}
diff --git a/packages/flutter/lib/src/http/mock_client.dart b/packages/flutter/lib/src/http/mock_client.dart
deleted file mode 100644
index 9b44e84..0000000
--- a/packages/flutter/lib/src/http/mock_client.dart
+++ /dev/null
@@ -1,88 +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.
-
-import 'dart:async';
-import 'dart:typed_data';
-
-import 'base_client.dart';
-import 'base_request.dart';
-import 'byte_stream.dart';
-import 'request.dart';
-import 'response.dart';
-import 'streamed_response.dart';
-
-// TODO(nweiz): once Dart has some sort of Rack- or WSGI-like standard for
-// server APIs, MockClient should conform to it.
-
-/// A mock HTTP client designed for use when testing code that uses
-/// [BaseClient]. This client allows you to define a handler callback for all
-/// requests that are made through it so that you can mock a server without
-/// having to send real HTTP requests.
-class MockClient extends BaseClient {
-  /// The handler for receiving [StreamedRequest]s and sending
-  /// [StreamedResponse]s.
-  final MockClientStreamHandler _handler;
-
-  /// Creates a [MockClient] with a handler that receives [Request]s and sends
-  /// [Response]s.
-  MockClient(MockClientHandler fn)
-    : this._((BaseRequest baseRequest, ByteStream bodyStream) {
-      return bodyStream.toBytes().then((Uint8List bodyBytes) {
-        Request request = new Request(baseRequest.method, baseRequest.url)
-            ..persistentConnection = baseRequest.persistentConnection
-            ..followRedirects = baseRequest.followRedirects
-            ..maxRedirects = baseRequest.maxRedirects
-            ..headers.addAll(baseRequest.headers)
-            ..bodyBytes = bodyBytes
-            ..finalize();
-
-        return fn(request);
-      }).then((Response response) {
-        return new StreamedResponse(
-            new ByteStream.fromBytes(response.bodyBytes),
-            response.statusCode,
-            contentLength: response.contentLength,
-            request: baseRequest,
-            headers: response.headers,
-            isRedirect: response.isRedirect,
-            persistentConnection: response.persistentConnection,
-            reasonPhrase: response.reasonPhrase);
-      });
-    });
-
-  MockClient._(this._handler);
-
-  /// Creates a [MockClient] with a handler that receives [StreamedRequest]s and
-  /// sends [StreamedResponse]s.
-  MockClient.streaming(MockClientStreamHandler fn)
-    : this._((BaseRequest request, ByteStream bodyStream) {
-      return fn(request, bodyStream).then((StreamedResponse response) {
-        return new StreamedResponse(
-            response.stream,
-            response.statusCode,
-            contentLength: response.contentLength,
-            request: request,
-            headers: response.headers,
-            isRedirect: response.isRedirect,
-            persistentConnection: response.persistentConnection,
-            reasonPhrase: response.reasonPhrase);
-      });
-    });
-
-  /// Sends a request.
-  @override
-  Future<StreamedResponse> send(BaseRequest request) async {
-    ByteStream bodyStream = request.finalize();
-    return await _handler(request, bodyStream);
-  }
-}
-
-/// A handler function that receives [StreamedRequest]s and sends
-/// [StreamedResponse]s. Note that [request] will be finalized.
-typedef Future<StreamedResponse> MockClientStreamHandler(
-    BaseRequest request, ByteStream bodyStream);
-
-/// A handler function that receives [Request]s and sends [Response]s. Note that
-/// [request] will be finalized.
-typedef Future<Response> MockClientHandler(BaseRequest request);
diff --git a/packages/flutter/lib/src/http/multipart_file.dart b/packages/flutter/lib/src/http/multipart_file.dart
deleted file mode 100644
index a21e624..0000000
--- a/packages/flutter/lib/src/http/multipart_file.dart
+++ /dev/null
@@ -1,111 +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.
-
-import 'dart:async';
-import 'dart:convert';
-
-import 'package:async/async.dart';
-import 'package:http_parser/http_parser.dart';
-import 'package:path/path.dart' as path;
-
-import 'byte_stream.dart';
-import 'io.dart' as io;
-import 'utils.dart';
-
-/// A file to be uploaded as part of a [MultipartRequest]. This doesn't need to
-/// correspond to a physical file.
-class MultipartFile {
-  /// The name of the form field for the file.
-  final String field;
-
-  /// The size of the file in bytes. This must be known in advance, even if this
-  /// file is created from a [ByteStream].
-  final int length;
-
-  /// The basename of the file. May be null.
-  final String filename;
-
-  /// The content-type of the file. Defaults to `application/octet-stream`.
-  final MediaType contentType;
-
-  /// The stream that will emit the file's contents.
-  final ByteStream _stream;
-
-  /// Creates a new [MultipartFile] from a chunked [Stream] of bytes. The length
-  /// of the file in bytes must be known in advance. If it's not, read the data
-  /// from the stream and use [MultipartFile.fromBytes] instead.
-  ///
-  /// [contentType] currently defaults to `application/octet-stream`, but in the
-  /// future may be inferred from [filename].
-  MultipartFile(this.field, Stream<List<int>> stream, this.length,
-      {this.filename, MediaType contentType})
-    : this._stream = toByteStream(stream),
-      this.contentType = contentType != null ? contentType :
-          new MediaType("application", "octet-stream");
-
-  /// Creates a new [MultipartFile] from a byte array.
-  ///
-  /// [contentType] currently defaults to `application/octet-stream`, but in the
-  /// future may be inferred from [filename].
-  factory MultipartFile.fromBytes(String field, List<int> value,
-      {String filename, MediaType contentType}) {
-    ByteStream stream = new ByteStream.fromBytes(value);
-    return new MultipartFile(field, stream, value.length,
-        filename: filename,
-        contentType: contentType);
-  }
-
-  /// Creates a new [MultipartFile] from a string.
-  ///
-  /// The encoding to use when translating [value] into bytes is taken from
-  /// [contentType] if it has a charset set. Otherwise, it defaults to UTF-8.
-  /// [contentType] currently defaults to `text/plain; charset=utf-8`, but in
-  /// the future may be inferred from [filename].
-  factory MultipartFile.fromString(String field, String value,
-      {String filename, MediaType contentType}) {
-    contentType = contentType == null ? new MediaType("text", "plain")
-                                      : contentType;
-    Encoding encoding = encodingForCharset(contentType.parameters['charset'], UTF8);
-    contentType = contentType.change(parameters: <String, String>{'charset': encoding.name});
-
-    return new MultipartFile.fromBytes(field, encoding.encode(value),
-        filename: filename,
-        contentType: contentType);
-  }
-
-  /// Whether [finalize] has been called.
-  bool get isFinalized => _isFinalized;
-  bool _isFinalized = false;
-
-  // TODO(nweiz): Infer the content-type from the filename.
-  /// Creates a new [MultipartFile] from a path to a file on disk.
-  ///
-  /// [filename] defaults to the basename of [filePath]. [contentType] currently
-  /// defaults to `application/octet-stream`, but in the future may be inferred
-  /// from [filename].
-  ///
-  /// This can only be used in an environment that supports "dart:io".
-  static Future<MultipartFile> fromPath(String field, String filePath,
-      {String filename, MediaType contentType}) async {
-    io.assertSupported("MultipartFile.fromPath");
-    if (filename == null) filename = path.basename(filePath);
-    dynamic file = io.newFile(filePath);
-    int length = await file.length();
-    ByteStream stream = new ByteStream(DelegatingStream.typed(file.openRead()));
-    return new MultipartFile(field, stream, length,
-        filename: filename,
-        contentType: contentType);
-  }
-
-  // Finalizes the file in preparation for it being sent as part of a
-  // [MultipartRequest]. This returns a [ByteStream] that should emit the body
-  // of the file. The stream may be closed to indicate an empty file.
-  ByteStream finalize() {
-    if (isFinalized) {
-      throw new StateError("Can't finalize a finalized MultipartFile.");
-    }
-    _isFinalized = true;
-    return _stream;
-  }
-}
diff --git a/packages/flutter/lib/src/http/multipart_request.dart b/packages/flutter/lib/src/http/multipart_request.dart
deleted file mode 100644
index c108eda..0000000
--- a/packages/flutter/lib/src/http/multipart_request.dart
+++ /dev/null
@@ -1,177 +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.
-
-import 'dart:async';
-import 'dart:convert';
-import 'dart:math';
-
-import 'base_request.dart';
-import 'byte_stream.dart';
-import 'multipart_file.dart';
-import 'utils.dart';
-
-final RegExp _newlineRegExp = new RegExp(r"\r\n|\r|\n");
-
-/// A `multipart/form-data` request. Such a request has both string [fields],
-/// which function as normal form fields, and (potentially streamed) binary
-/// [files].
-///
-/// This request automatically sets the Content-Type header to
-/// `multipart/form-data`. This value will override any value set by the user.
-///
-///     var uri = Uri.parse("http://pub.dartlang.org/packages/create");
-///     var request = new http.MultipartRequest("POST", url);
-///     request.fields['user'] = 'nweiz@google.com';
-///     request.files.add(new http.MultipartFile.fromFile(
-///         'package',
-///         new File('build/package.tar.gz'),
-///         contentType: new MediaType('application', 'x-tar'));
-///     request.send().then((response) {
-///       if (response.statusCode == 200) print("Uploaded!");
-///     });
-class MultipartRequest extends BaseRequest {
-  /// The total length of the multipart boundaries used when building the
-  /// request body. According to http://tools.ietf.org/html/rfc1341.html, this
-  /// can't be longer than 70.
-  static const int _BOUNDARY_LENGTH = 70;
-
-  static final Random _random = new Random();
-
-  /// The form fields to send for this request.
-  final Map<String, String> fields;
-
-  /// The private version of [files].
-  final List<MultipartFile> _files;
-
-  /// Creates a new [MultipartRequest].
-  MultipartRequest(String method, Uri url)
-    : fields = <String, String>{},
-      _files = <MultipartFile>[],
-      super(method, url);
-
-  /// The list of files to upload for this request.
-  List<MultipartFile> get files => _files;
-
-  /// The total length of the request body, in bytes. This is calculated from
-  /// [fields] and [files] and cannot be set manually.
-  @override
-  int get contentLength {
-    int length = 0;
-
-    fields.forEach((String name, String value) {
-      length += "--".length + _BOUNDARY_LENGTH + "\r\n".length +
-          UTF8.encode(_headerForField(name, value)).length +
-          UTF8.encode(value).length + "\r\n".length;
-    });
-
-    for (MultipartFile file in _files) {
-      length += "--".length + _BOUNDARY_LENGTH + "\r\n".length +
-          UTF8.encode(_headerForFile(file)).length +
-          file.length + "\r\n".length;
-    }
-
-    return length + "--".length + _BOUNDARY_LENGTH + "--\r\n".length;
-  }
-
-  @override
-  set contentLength(int value) {
-    throw new UnsupportedError("Cannot set the contentLength property of "
-        "multipart requests.");
-  }
-
-  /// Freezes all mutable fields and returns a single-subscription [ByteStream]
-  /// that will emit the request body.
-  @override
-  ByteStream finalize() {
-    // TODO(nweiz): freeze fields and files
-    String boundary = _boundaryString();
-    headers['content-type'] = 'multipart/form-data; boundary="$boundary"';
-    super.finalize();
-
-    StreamController<List<int>> controller = new StreamController<List<int>>(sync: true);
-
-    void writeAscii(String string) {
-      controller.add(UTF8.encode(string));
-    }
-
-    dynamic writeUtf8(String string) => controller.add(UTF8.encode(string));
-    dynamic writeLine() => controller.add(<int>[13, 10]); // \r\n
-
-    fields.forEach((String name, String value) {
-      writeAscii('--$boundary\r\n');
-      writeAscii(_headerForField(name, value));
-      writeUtf8(value);
-      writeLine();
-    });
-
-    Future.forEach(_files, (MultipartFile file) {
-      writeAscii('--$boundary\r\n');
-      writeAscii(_headerForFile(file));
-      return writeStreamToSink(file.finalize(), controller)
-        .then((_) => writeLine());
-    }).then((_) {
-      // TODO(nweiz): pass any errors propagated through this future on to
-      // the stream. See issue 3657.
-      writeAscii('--$boundary--\r\n');
-      controller.close();
-    });
-
-    return new ByteStream(controller.stream);
-  }
-
-  /// All character codes that are valid in multipart boundaries. From
-  /// http://tools.ietf.org/html/rfc2046#section-5.1.1.
-  static const List<int> _BOUNDARY_CHARACTERS = const <int>[
-    39, 40, 41, 43, 95, 44, 45, 46, 47, 58, 61, 63, 48, 49, 50, 51, 52, 53, 54,
-    55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
-    81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103,
-    104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
-    119, 120, 121, 122
-  ];
-
-  /// Returns the header string for a field. The return value is guaranteed to
-  /// contain only ASCII characters.
-  String _headerForField(String name, String value) {
-    String header =
-        'content-disposition: form-data; name="${_browserEncode(name)}"';
-    if (!isPlainAscii(value)) {
-      header = '$header\r\n'
-          'content-type: text/plain; charset=utf-8\r\n'
-          'content-transfer-encoding: binary';
-    }
-    return '$header\r\n\r\n';
-  }
-
-  /// Returns the header string for a file. The return value is guaranteed to
-  /// contain only ASCII characters.
-  String _headerForFile(MultipartFile file) {
-    String header = 'content-type: ${file.contentType}\r\n'
-      'content-disposition: form-data; name="${_browserEncode(file.field)}"';
-
-    if (file.filename != null) {
-      header = '$header; filename="${_browserEncode(file.filename)}"';
-    }
-    return '$header\r\n\r\n';
-  }
-
-  /// Encode [value] in the same way browsers do.
-  String _browserEncode(String value) {
-    // http://tools.ietf.org/html/rfc2388 mandates some complex encodings for
-    // field names and file names, but in practice user agents seem not to
-    // follow this at all. Instead, they URL-encode `\r`, `\n`, and `\r\n` as
-    // `\r\n`; URL-encode `"`; and do nothing else (even for `%` or non-ASCII
-    // characters). We follow their behavior.
-    return value.replaceAll(_newlineRegExp, "%0D%0A").replaceAll('"', "%22");
-  }
-
-  /// Returns a randomly-generated multipart boundary string
-  String _boundaryString() {
-    String prefix = "dart-http-boundary-";
-    List<int> list = new List<int>.generate(_BOUNDARY_LENGTH - prefix.length,
-        (int index) =>
-            _BOUNDARY_CHARACTERS[_random.nextInt(_BOUNDARY_CHARACTERS.length)],
-        growable: false);
-    return "$prefix${new String.fromCharCodes(list)}";
-  }
-}
diff --git a/packages/flutter/lib/src/http/request.dart b/packages/flutter/lib/src/http/request.dart
deleted file mode 100644
index 495e663..0000000
--- a/packages/flutter/lib/src/http/request.dart
+++ /dev/null
@@ -1,164 +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.
-
-import 'dart:convert';
-import 'dart:typed_data';
-
-import 'package:http_parser/http_parser.dart';
-
-import 'base_request.dart';
-import 'byte_stream.dart';
-import 'utils.dart';
-
-/// An HTTP request where the entire request body is known in advance.
-class Request extends BaseRequest {
-  /// Creates a new HTTP request.
-  Request(String method, Uri url)
-    : _defaultEncoding = UTF8,
-      _bodyBytes = new Uint8List(0),
-      super(method, url);
-
-  /// The size of the request body, in bytes. This is calculated from
-  /// [bodyBytes].
-  ///
-  /// The content length cannot be set for [Request], since it's automatically
-  /// calculated from [bodyBytes].
-  @override
-  int get contentLength => bodyBytes.length;
-
-  @override
-  set contentLength(int value) {
-    throw new UnsupportedError("Cannot set the contentLength property of "
-        "non-streaming Request objects.");
-  }
-
-  /// The default encoding to use when converting between [bodyBytes] and
-  /// [body]. This is only used if [encoding] hasn't been manually set and if
-  /// the content-type header has no encoding information.
-  Encoding _defaultEncoding;
-
-  /// The encoding used for the request. This encoding is used when converting
-  /// between [bodyBytes] and [body].
-  ///
-  /// If the request has a `Content-Type` header and that header has a `charset`
-  /// parameter, that parameter's value is used as the encoding. Otherwise, if
-  /// [encoding] has been set manually, that encoding is used. If that hasn't
-  /// been set either, this defaults to [UTF8].
-  ///
-  /// If the `charset` parameter's value is not a known [Encoding], reading this
-  /// will throw a [FormatException].
-  ///
-  /// If the request has a `Content-Type` header, setting this will set the
-  /// charset parameter on that header.
-  Encoding get encoding {
-    if (_contentType == null ||
-        !_contentType.parameters.containsKey('charset')) {
-      return _defaultEncoding;
-    }
-    return requiredEncodingForCharset(_contentType.parameters['charset']);
-  }
-
-  set encoding(Encoding value) {
-    _checkFinalized();
-    _defaultEncoding = value;
-    MediaType contentType = _contentType;
-    if (contentType == null) return;
-    _contentType = contentType.change(parameters: <String, String>{'charset': value.name});
-  }
-
-  // TODO(nweiz): make this return a read-only view
-  /// The bytes comprising the body of the request. This is converted to and
-  /// from [body] using [encoding].
-  ///
-  /// This list should only be set, not be modified in place.
-  Uint8List get bodyBytes => _bodyBytes;
-  Uint8List _bodyBytes;
-
-  set bodyBytes(List<int> value) {
-    _checkFinalized();
-    _bodyBytes = toUint8List(value);
-  }
-
-  /// The body of the request as a string. This is converted to and from
-  /// [bodyBytes] using [encoding].
-  ///
-  /// When this is set, if the request does not yet have a `Content-Type`
-  /// header, one will be added with the type `text/plain`. Then the `charset`
-  /// parameter of the `Content-Type` header (whether new or pre-existing) will
-  /// be set to [encoding] if it wasn't already set.
-  String get body => encoding.decode(bodyBytes);
-
-  set body(String value) {
-    bodyBytes = encoding.encode(value);
-    MediaType contentType = _contentType;
-    if (contentType == null) {
-      _contentType = new MediaType("text", "plain", <String, String>{'charset': encoding.name});
-    } else if (!contentType.parameters.containsKey('charset')) {
-      _contentType = contentType.change(parameters: <String, String>{'charset': encoding.name});
-    }
-  }
-
-  /// The form-encoded fields in the body of the request as a map from field
-  /// names to values. The form-encoded body is converted to and from
-  /// [bodyBytes] using [encoding] (in the same way as [body]).
-  ///
-  /// If the request doesn't have a `Content-Type` header of
-  /// `application/x-www-form-urlencoded`, reading this will throw a
-  /// [StateError].
-  ///
-  /// If the request has a `Content-Type` header with a type other than
-  /// `application/x-www-form-urlencoded`, setting this will throw a
-  /// [StateError]. Otherwise, the content type will be set to
-  /// `application/x-www-form-urlencoded`.
-  ///
-  /// This map should only be set, not modified in place.
-  Map<String, String> get bodyFields {
-    MediaType contentType = _contentType;
-    if (contentType == null ||
-        contentType.mimeType != "application/x-www-form-urlencoded") {
-      throw new StateError('Cannot access the body fields of a Request without '
-          'content-type "application/x-www-form-urlencoded".');
-    }
-
-    return Uri.splitQueryString(body, encoding: encoding);
-  }
-
-  set bodyFields(Map<String, String> fields) {
-    MediaType contentType = _contentType;
-    if (contentType == null) {
-      _contentType = new MediaType("application", "x-www-form-urlencoded");
-    } else if (contentType.mimeType != "application/x-www-form-urlencoded") {
-      throw new StateError('Cannot set the body fields of a Request with '
-          'content-type "${contentType.mimeType}".');
-    }
-
-    this.body = mapToQuery(fields, encoding: encoding);
-  }
-
-  /// Freezes all mutable fields and returns a single-subscription [ByteStream]
-  /// containing the request body.
-  @override
-  ByteStream finalize() {
-    super.finalize();
-    return new ByteStream.fromBytes(bodyBytes);
-  }
-
-  /// The `Content-Type` header of the request (if it exists) as a
-  /// [MediaType].
-  MediaType get _contentType {
-    String contentType = headers['content-type'];
-    if (contentType == null) return null;
-    return new MediaType.parse(contentType);
-  }
-
-  set _contentType(MediaType value) {
-    headers['content-type'] = value.toString();
-  }
-
-  /// Throw an error if this request has been finalized.
-  void _checkFinalized() {
-    if (!finalized) return;
-    throw new StateError("Can't modify a finalized Request.");
-  }
-}
diff --git a/packages/flutter/lib/src/http/response.dart b/packages/flutter/lib/src/http/response.dart
deleted file mode 100644
index caba63b..0000000
--- a/packages/flutter/lib/src/http/response.dart
+++ /dev/null
@@ -1,95 +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.
-
-import 'dart:async';
-import 'dart:convert';
-import 'dart:typed_data';
-
-import 'package:http_parser/http_parser.dart';
-
-import 'base_request.dart';
-import 'base_response.dart';
-import 'streamed_response.dart';
-import 'utils.dart';
-
-/// An HTTP response where the entire response body is known in advance.
-class Response extends BaseResponse {
-  /// The bytes comprising the body of this response.
-  final Uint8List bodyBytes;
-
-  /// Creates a new HTTP response with a string body.
-  Response(
-      String body,
-      int statusCode,
-      {BaseRequest request,
-       Map<String, String> headers: const <String, String>{},
-       bool isRedirect: false,
-       bool persistentConnection: true,
-       String reasonPhrase})
-    : this.bytes(
-        _encodingForHeaders(headers).encode(body),
-        statusCode,
-        request: request,
-        headers: headers,
-        isRedirect: isRedirect,
-        persistentConnection: persistentConnection,
-        reasonPhrase: reasonPhrase);
-
-  /// Create a new HTTP response with a byte array body.
-  Response.bytes(
-      List<int> bodyBytes,
-      int statusCode,
-      {BaseRequest request,
-       Map<String, String> headers: const <String, String>{},
-       bool isRedirect: false,
-       bool persistentConnection: true,
-       String reasonPhrase})
-    : bodyBytes = toUint8List(bodyBytes),
-      super(
-        statusCode,
-        contentLength: bodyBytes.length,
-        request: request,
-        headers: headers,
-        isRedirect: isRedirect,
-        persistentConnection: persistentConnection,
-        reasonPhrase: reasonPhrase);
-
-  /// The body of the response as a string. This is converted from [bodyBytes]
-  /// using the `charset` parameter of the `Content-Type` header field, if
-  /// available. If it's unavailable or if the encoding name is unknown,
-  /// [LATIN1] is used by default, as per [RFC 2616][].
-  ///
-  /// [RFC 2616]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html
-  String get body => _encodingForHeaders(headers).decode(bodyBytes);
-
-  /// Creates a new HTTP response by waiting for the full body to become
-  /// available from a [StreamedResponse].
-  static Future<Response> fromStream(StreamedResponse response) {
-    return response.stream.toBytes().then((List<int> body) {
-      return new Response.bytes(
-          body,
-          response.statusCode,
-          request: response.request,
-          headers: response.headers,
-          isRedirect: response.isRedirect,
-          persistentConnection: response.persistentConnection,
-          reasonPhrase: response.reasonPhrase);
-    });
-  }
-}
-
-/// Returns the encoding to use for a response with the given headers. This
-/// defaults to [LATIN1] if the headers don't specify a charset or
-/// if that charset is unknown.
-Encoding _encodingForHeaders(Map<String, String> headers) =>
-  encodingForCharset(_contentTypeForHeaders(headers).parameters['charset']);
-
-/// Returns the [MediaType] object for the given headers's content-type.
-///
-/// Defaults to `application/octet-stream`.
-MediaType _contentTypeForHeaders(Map<String, String> headers) {
-  String contentType = headers['content-type'];
-  if (contentType != null) return new MediaType.parse(contentType);
-  return new MediaType("application", "octet-stream");
-}
diff --git a/packages/flutter/lib/src/http/streamed_request.dart b/packages/flutter/lib/src/http/streamed_request.dart
deleted file mode 100644
index 8d1b408..0000000
--- a/packages/flutter/lib/src/http/streamed_request.dart
+++ /dev/null
@@ -1,42 +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.
-
-import 'dart:async';
-
-import 'byte_stream.dart';
-import 'base_request.dart';
-
-/// An HTTP request where the request body is sent asynchronously after the
-/// connection has been established and the headers have been sent.
-///
-/// When the request is sent via [BaseClient.send], only the headers and
-/// whatever data has already been written to [StreamedRequest.stream] will be
-/// sent immediately. More data will be sent as soon as it's written to
-/// [StreamedRequest.sink], and when the sink is closed the request will end.
-class StreamedRequest extends BaseRequest {
-  /// Creates a new streaming request.
-  StreamedRequest(String method, Uri url)
-    : _controller = new StreamController<List<int>>(sync: true),
-      super(method, url);
-
-  /// The sink to which to write data that will be sent as the request body.
-  /// This may be safely written to before the request is sent; the data will be
-  /// buffered.
-  ///
-  /// Closing this signals the end of the request.
-  EventSink<List<int>> get sink => _controller.sink;
-
-  /// The controller for [sink], from which [BaseRequest] will read data for
-  /// [finalize].
-  final StreamController<List<int>> _controller;
-
-  /// Freezes all mutable fields other than [stream] and returns a
-  /// single-subscription [ByteStream] that emits the data being written to
-  /// [sink].
-  @override
-  ByteStream finalize() {
-    super.finalize();
-    return new ByteStream(_controller.stream);
-  }
-}
diff --git a/packages/flutter/lib/src/http/streamed_response.dart b/packages/flutter/lib/src/http/streamed_response.dart
deleted file mode 100644
index a23a952..0000000
--- a/packages/flutter/lib/src/http/streamed_response.dart
+++ /dev/null
@@ -1,39 +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.
-
-import 'dart:async';
-
-import 'byte_stream.dart';
-import 'base_response.dart';
-import 'base_request.dart';
-import 'utils.dart';
-
-/// An HTTP response where the response body is received asynchronously after
-/// the headers have been received.
-class StreamedResponse extends BaseResponse {
-  /// The stream from which the response body data can be read. This should
-  /// always be a single-subscription stream.
-  final ByteStream stream;
-
-  /// Creates a new streaming response. [stream] should be a single-subscription
-  /// stream.
-  StreamedResponse(
-      Stream<List<int>> stream,
-      int statusCode,
-      {int contentLength,
-       BaseRequest request,
-       Map<String, String> headers: const <String, String> {},
-       bool isRedirect: false,
-       bool persistentConnection: true,
-       String reasonPhrase})
-    : this.stream = toByteStream(stream),
-      super(
-          statusCode,
-          contentLength: contentLength,
-          request: request,
-          headers: headers,
-          isRedirect: isRedirect,
-          persistentConnection: persistentConnection,
-          reasonPhrase: reasonPhrase);
-}
diff --git a/packages/flutter/lib/src/http/utils.dart b/packages/flutter/lib/src/http/utils.dart
deleted file mode 100644
index 4617269..0000000
--- a/packages/flutter/lib/src/http/utils.dart
+++ /dev/null
@@ -1,143 +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.
-
-import 'dart:async';
-import 'dart:convert';
-import 'dart:typed_data';
-
-import 'byte_stream.dart';
-
-/// Converts a [Map] from parameter names to values to a URL query string.
-///
-///     mapToQuery({"foo": "bar", "baz": "bang"});
-///     //=> "foo=bar&baz=bang"
-String mapToQuery(Map<String, String> map, {Encoding encoding}) {
-  List<List<String>> pairs = <List<String>>[];
-  map.forEach((String key, String value) =>
-      pairs.add(<String>[Uri.encodeQueryComponent(key, encoding: encoding),
-                 Uri.encodeQueryComponent(value, encoding: encoding)]));
-  return pairs.map((List<String> pair) => "${pair[0]}=${pair[1]}").join("&");
-}
-
-/// Like [String.split], but only splits on the first occurrence of the pattern.
-/// This will always return an array of two elements or fewer.
-///
-///     split1("foo,bar,baz", ","); //=> ["foo", "bar,baz"]
-///     split1("foo", ","); //=> ["foo"]
-///     split1("", ","); //=> []
-List<String> split1(String toSplit, String pattern) {
-  if (toSplit.isEmpty) return <String>[];
-
-  int index = toSplit.indexOf(pattern);
-  if (index == -1) return <String>[toSplit];
-  return <String>[
-    toSplit.substring(0, index),
-    toSplit.substring(index + pattern.length)
-  ];
-}
-
-/// Returns the [Encoding] that corresponds to [charset]. Returns [fallback] if
-/// [charset] is null or if no [Encoding] was found that corresponds to
-/// [charset].
-Encoding encodingForCharset(String charset, [Encoding fallback = LATIN1]) {
-  if (charset == null) return fallback;
-  Encoding encoding = Encoding.getByName(charset);
-  return encoding == null ? fallback : encoding;
-}
-
-
-/// Returns the [Encoding] that corresponds to [charset]. Throws a
-/// [FormatException] if no [Encoding] was found that corresponds to [charset].
-/// [charset] may not be null.
-Encoding requiredEncodingForCharset(String charset) {
-  Encoding encoding = Encoding.getByName(charset);
-  if (encoding != null) return encoding;
-  throw new FormatException('Unsupported encoding "$charset".');
-}
-
-/// A regular expression that matches strings that are composed entirely of
-/// ASCII-compatible characters.
-final RegExp _kAsciiOnly = new RegExp(r"^[\x00-\x7F]+$");
-
-/// Returns whether [string] is composed entirely of ASCII-compatible
-/// characters.
-bool isPlainAscii(String string) => _kAsciiOnly.hasMatch(string);
-
-/// Converts [input] into a [Uint8List].
-///
-/// If [input] is a [TypedData], this just returns a view on [input].
-Uint8List toUint8List(dynamic input) {
-  if (input is Uint8List)
-    return input;
-  if (input is TypedData)
-    return new Uint8List.view(input.buffer);
-  return new Uint8List.fromList(input);
-}
-
-/// If [stream] is already a [ByteStream], returns it. Otherwise, wraps it in a
-/// [ByteStream].
-ByteStream toByteStream(Stream<List<int>> stream) {
-  if (stream is ByteStream) return stream;
-  return new ByteStream(stream);
-}
-
-/// Calls [onDone] once [stream] (a single-subscription [Stream]) is finished.
-/// The return value, also a single-subscription [Stream] should be used in
-/// place of [stream] after calling this method.
-Stream/*<T>*/ onDone/*<T>*/(Stream/*<T>*/ stream, void onDone()) =>
-    stream.transform(new StreamTransformer.fromHandlers(handleDone: (EventSink<dynamic> sink) { // ignore: always_specify_types
-      sink.close();
-      onDone();
-    }));
-
-// TODO(nweiz): remove this when issue 7786 is fixed.
-/// Pipes all data and errors from [stream] into [sink]. When [stream] is done,
-/// [sink] is closed and the returned [Future] is completed.
-Future<dynamic> store(Stream<dynamic> stream, EventSink<dynamic> sink) {
-  Completer<dynamic> completer = new Completer<dynamic>();
-  stream.listen(sink.add,
-      onError: sink.addError,
-      onDone: () {
-        sink.close();
-        completer.complete();
-      });
-  return completer.future;
-}
-
-/// Pipes all data and errors from [stream] into [sink]. Completes [Future] once
-/// [stream] is done. Unlike [store], [sink] remains open after [stream] is
-/// done.
-Future<dynamic> writeStreamToSink(Stream<dynamic> stream, EventSink<dynamic> sink) {
-  Completer<dynamic> completer = new Completer<dynamic>();
-  stream.listen(sink.add,
-      onError: sink.addError,
-      onDone: () => completer.complete());
-  return completer.future;
-}
-
-/// A pair of values.
-class Pair<E, F> {
-  E first;
-  F last;
-
-  Pair(this.first, this.last);
-
-  @override
-  String toString() => '($first, $last)';
-
-  @override
-  bool operator==(dynamic other) {
-    if (other is! Pair) return false;
-    return other.first == first && other.last == last;
-  }
-
-  @override
-  int get hashCode => first.hashCode ^ last.hashCode;
-}
-
-/// Configures [future] so that its result (success or exception) is passed on
-/// to [completer].
-void chainToCompleter(Future<dynamic> future, Completer<dynamic> completer) {
-  future.then(completer.complete, onError: completer.completeError);
-}
diff --git a/packages/flutter/lib/src/services/asset_bundle.dart b/packages/flutter/lib/src/services/asset_bundle.dart
index 373aa84..d649952 100644
--- a/packages/flutter/lib/src/services/asset_bundle.dart
+++ b/packages/flutter/lib/src/services/asset_bundle.dart
@@ -7,9 +7,10 @@
 import 'dart:typed_data';
 
 import 'package:flutter/foundation.dart';
-import 'package:flutter/http.dart' as http;
+import 'package:http/http.dart' as http;
 
 import 'platform_messages.dart';
+import 'http_client.dart';
 
 /// A collection of resources used by the application.
 ///
@@ -84,15 +85,18 @@
 class NetworkAssetBundle extends AssetBundle {
   /// Creates an network asset bundle that resolves asset keys as URLs relative
   /// to the given base URL.
-  NetworkAssetBundle(Uri baseUrl) : _baseUrl = baseUrl;
+  NetworkAssetBundle(Uri baseUrl)
+    : _baseUrl = baseUrl,
+      _httpClient = createHttpClient();
 
   final Uri _baseUrl;
+  final http.Client _httpClient;
 
   String _urlFromKey(String key) => _baseUrl.resolve(key).toString();
 
   @override
   Future<ByteData> load(String key) async {
-    final http.Response response = await http.get(_urlFromKey(key));
+    final http.Response response = await _httpClient.get(_urlFromKey(key));
     if (response.statusCode == 200)
       return null;
     return response.bodyBytes.buffer.asByteData();
@@ -100,7 +104,7 @@
 
   @override
   Future<String> loadString(String key, { bool cache: true }) async {
-    final http.Response response = await http.get(_urlFromKey(key));
+    final http.Response response = await _httpClient.get(_urlFromKey(key));
     return response.statusCode == 200 ? response.body : null;
   }
 
diff --git a/packages/flutter/lib/src/services/http_client.dart b/packages/flutter/lib/src/services/http_client.dart
new file mode 100644
index 0000000..2a058d8
--- /dev/null
+++ b/packages/flutter/lib/src/services/http_client.dart
@@ -0,0 +1,16 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter/foundation.dart';
+import 'package:http/http.dart' as http;
+
+/// Create a new [http.Client] object.
+///
+/// This can be set to a new function to override the default logic for creating
+/// HTTP clients, for example so that all logic in the framework that triggers
+/// HTTP requests will use the same `UserAgent` header, or so that tests can
+/// provide an [http.MockClient].
+ValueGetter<http.Client> createHttpClient = () {
+  return new http.Client();
+};
diff --git a/packages/flutter/lib/src/services/image_provider.dart b/packages/flutter/lib/src/services/image_provider.dart
index 1d59abc..ab83712 100644
--- a/packages/flutter/lib/src/services/image_provider.dart
+++ b/packages/flutter/lib/src/services/image_provider.dart
@@ -9,9 +9,10 @@
 import 'dart:ui' show Size, Locale, hashValues;
 
 import 'package:flutter/foundation.dart';
-import 'package:flutter/http.dart' as http;
+import 'package:http/http.dart' as http;
 
 import 'asset_bundle.dart';
+import 'http_client.dart';
 import 'image_cache.dart';
 import 'image_decoder.dart';
 import 'image_stream.dart';
@@ -332,11 +333,13 @@
     );
   }
 
+  static final http.Client _httpClient = createHttpClient();
+
   Future<ImageInfo> _loadAsync(NetworkImage key) async {
     assert(key == this);
 
     final Uri resolved = Uri.base.resolve(key.url);
-    final http.Response response = await http.get(resolved);
+    final http.Response response = await _httpClient.get(resolved);
     if (response == null || response.statusCode != 200)
       return null;
 
diff --git a/packages/flutter/pubspec.yaml b/packages/flutter/pubspec.yaml
index 7a3651b..4a8eae1 100644
--- a/packages/flutter/pubspec.yaml
+++ b/packages/flutter/pubspec.yaml
@@ -6,15 +6,11 @@
 
 dependencies:
   collection: '>=1.9.1 <2.0.0'
+  http: '>=0.11.3+11'
   intl: '>=0.14.0 <0.15.0'
   meta: ^1.0.4
   vector_math: '>=2.0.3 <3.0.0'
 
-  # async and http_parser can be removed when we move to using dart-lang/http
-  # directly.
-  async: "^1.10.0"
-  http_parser: ">=0.0.1 <4.0.0"
-
   sky_engine:
     path: ../../bin/cache/pkg/sky_engine
 
diff --git a/packages/flutter_test/lib/src/binding.dart b/packages/flutter_test/lib/src/binding.dart
index 38498e7..e1f8f31 100644
--- a/packages/flutter_test/lib/src/binding.dart
+++ b/packages/flutter_test/lib/src/binding.dart
@@ -8,10 +8,12 @@
 
 import 'package:flutter/foundation.dart';
 import 'package:flutter/gestures.dart';
-import 'package:flutter/http.dart' as http;
 import 'package:flutter/rendering.dart';
 import 'package:flutter/scheduler.dart';
+import 'package:flutter/services.dart';
 import 'package:flutter/widgets.dart';
+import 'package:http/http.dart' as http;
+import 'package:http/testing.dart' as http;
 import 'package:meta/meta.dart';
 import 'package:quiver/testing/async.dart';
 import 'package:quiver/time.dart';
@@ -119,7 +121,7 @@
   @override
   void initInstances() {
     timeDilation = 1.0; // just in case the developer has artificially changed it for development
-    http.Client.clientOverride = () {
+    createHttpClient = () {
       return new http.MockClient((http.BaseRequest request) {
         return new Future<http.Response>.value(
           new http.Response("Mocked: Unavailable.", 404, request: request)