diff --git a/lib/http.dart b/lib/http.dart
index 9ccd77a6f8..f59c19e732 100644
--- a/lib/http.dart
+++ b/lib/http.dart
@@ -11,8 +11,6 @@ import 'src/client.dart';
 import 'src/response.dart';
 
 export 'src/base_client.dart';
-export 'src/base_request.dart';
-export 'src/base_response.dart';
 export 'src/byte_stream.dart';
 export 'src/client.dart';
 export 'src/exception.dart';
@@ -21,8 +19,6 @@ export 'src/multipart_file.dart';
 export 'src/multipart_request.dart';
 export 'src/request.dart';
 export 'src/response.dart';
-export 'src/streamed_request.dart';
-export 'src/streamed_response.dart';
 
 /// Sends an HTTP HEAD request with the given headers to the given URL, which
 /// can be a [Uri] or a [String].
@@ -65,10 +61,10 @@ Future<Response> get(url, {Map<String, String> headers}) =>
 ///
 /// For more fine-grained control over the request, use [Request] or
 /// [StreamedRequest] instead.
-Future<Response> post(url, {Map<String, String> headers, body,
+Future<Response> post(url, body, {Map<String, String> headers,
     Encoding encoding}) =>
-  _withClient((client) => client.post(url,
-      headers: headers, body: body, encoding: encoding));
+  _withClient((client) => client.post(url, body,
+      headers: headers, 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].
@@ -89,10 +85,10 @@ Future<Response> post(url, {Map<String, String> headers, body,
 ///
 /// For more fine-grained control over the request, use [Request] or
 /// [StreamedRequest] instead.
-Future<Response> put(url, {Map<String, String> headers, body,
+Future<Response> put(url, body, {Map<String, String> headers,
     Encoding encoding}) =>
-  _withClient((client) => client.put(url,
-      headers: headers, body: body, encoding: encoding));
+  _withClient((client) => client.put(url, body,
+      headers: headers, 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].
@@ -113,10 +109,10 @@ Future<Response> put(url, {Map<String, String> headers, body,
 ///
 /// For more fine-grained control over the request, use [Request] or
 /// [StreamedRequest] instead.
-Future<Response> patch(url, {Map<String, String> headers, body,
+Future<Response> patch(url, body, {Map<String, String> headers,
     Encoding encoding}) =>
-  _withClient((client) => client.patch(url,
-      headers: headers, body: body, encoding: encoding));
+  _withClient((client) => client.patch(url, body,
+      headers: headers, encoding: encoding));
 
 /// Sends an HTTP DELETE request with the given headers to the given URL, which
 /// can be a [Uri] or a [String].
@@ -161,7 +157,7 @@ Future<String> read(url, {Map<String, String> headers}) =>
 Future<Uint8List> readBytes(url, {Map<String, String> headers}) =>
   _withClient((client) => client.readBytes(url, headers: headers));
 
-Future/*<T>*/ _withClient/*<T>*/(Future/*<T>*/ fn(Client client)) async {
+Future<T> _withClient<T>(Future<T> fn(Client client)) async {
   var client = new Client();
   try {
     return await fn(client);
diff --git a/lib/src/base_client.dart b/lib/src/base_client.dart
index 7b3fbfa41e..29dd1107e3 100644
--- a/lib/src/base_client.dart
+++ b/lib/src/base_client.dart
@@ -6,14 +6,12 @@ import 'dart:async';
 import 'dart:convert';
 import 'dart:typed_data';
 
-import 'package:collection/collection.dart';
+import 'package:async/async.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
@@ -24,14 +22,14 @@ abstract class BaseClient implements Client {
   ///
   /// For more fine-grained control over the request, use [send] instead.
   Future<Response> head(url, {Map<String, String> headers}) =>
-    _sendUnstreamed("HEAD", url, headers);
+    send(new Request.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].
   ///
   /// For more fine-grained control over the request, use [send] instead.
   Future<Response> get(url, {Map<String, String> headers}) =>
-    _sendUnstreamed("GET", url, headers);
+    send(new Request.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].
@@ -51,9 +49,10 @@ abstract class BaseClient implements Client {
   /// [encoding] defaults to UTF-8.
   ///
   /// For more fine-grained control over the request, use [send] instead.
-  Future<Response> post(url, {Map<String, String> headers, body,
+  Future<Response> post(url, body, {Map<String, String> headers,
       Encoding encoding}) =>
-    _sendUnstreamed("POST", url, headers, body, encoding);
+    send(new Request.post(url, body, headers: headers,
+        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].
@@ -73,9 +72,10 @@ abstract class BaseClient implements Client {
   /// [encoding] defaults to UTF-8.
   ///
   /// For more fine-grained control over the request, use [send] instead.
-  Future<Response> put(url, {Map<String, String> headers, body,
+  Future<Response> put(url, body, {Map<String, String> headers,
       Encoding encoding}) =>
-    _sendUnstreamed("PUT", url, headers, body, encoding);
+    send(new Request.put(url, body, headers: headers,
+        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].
@@ -95,16 +95,17 @@ abstract class BaseClient implements Client {
   /// [encoding] defaults to UTF-8.
   ///
   /// For more fine-grained control over the request, use [send] instead.
-  Future<Response> patch(url, {Map<String, String> headers, body,
+  Future<Response> patch(url, body, {Map<String, String> headers,
       Encoding encoding}) =>
-    _sendUnstreamed("PATCH", url, headers, body, encoding);
+    send(new Request.patch(url, body, headers: headers,
+        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(url, {Map<String, String> headers}) =>
-    _sendUnstreamed("DELETE", url, headers);
+      send(new Request.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
@@ -115,11 +116,11 @@ abstract class BaseClient implements Client {
   ///
   /// For more fine-grained control over the request and response, use [send] or
   /// [get] instead.
-  Future<String> read(url, {Map<String, String> headers}) {
-    return get(url, headers: headers).then((response) {
-      _checkResponseSuccess(url, response);
-      return response.body;
-    });
+  Future<String> read(url, {Map<String, String> headers}) async {
+    var response = await get(url, headers: headers);
+    _checkResponseSuccess(url, response);
+
+    return await response.readAsString();
   }
 
   /// Sends an HTTP GET request with the given headers to the given URL, which
@@ -131,11 +132,11 @@ abstract class BaseClient implements Client {
   ///
   /// For more fine-grained control over the request and response, use [send] or
   /// [get] instead.
-  Future<Uint8List> readBytes(url, {Map<String, String> headers}) {
-    return get(url, headers: headers).then((response) {
-      _checkResponseSuccess(url, response);
-      return response.bodyBytes;
-    });
+  Future<Uint8List> readBytes(url, {Map<String, String> headers}) async {
+    var response = await get(url, headers: headers);
+    _checkResponseSuccess(url, response);
+
+    return await collectBytes(response.read());
   }
 
   /// Sends an HTTP request and asynchronously returns the response.
@@ -145,31 +146,7 @@ abstract class BaseClient implements Client {
   /// 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.
-  Future<StreamedResponse> send(BaseRequest request);
-
-  /// Sends a non-streaming [Request] and returns a non-streaming [Response].
-  Future<Response> _sendUnstreamed(String method, url,
-      Map<String, String> headers, [body, Encoding encoding]) async {
-
-    if (url is String) url = Uri.parse(url);
-    var 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));
-  }
+  Future<Response> send(Request request);
 
   /// Throws an error if [response] is not successful.
   void _checkResponseSuccess(url, Response response) {
diff --git a/lib/src/base_request.dart b/lib/src/base_request.dart
deleted file mode 100644
index b11ef05ae5..0000000000
--- a/lib/src/base_request.dart
+++ /dev/null
@@ -1,140 +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;
-
-  /// 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;
-
-  /// Creates a new HTTP request.
-  BaseRequest(this.method, this.url)
-    : headers = new LinkedHashMap(
-        equals: (key1, key2) => key1.toLowerCase() == key2.toLowerCase(),
-        hashCode: (key) => key.toLowerCase().hashCode);
-
-  /// 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 {
-    var client = new Client();
-
-    try {
-      var response = await client.send(this);
-      var 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 (_) {
-      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.");
-  }
-
-  String toString() => "$method $url";
-}
diff --git a/lib/src/base_response.dart b/lib/src/base_response.dart
deleted file mode 100644
index 26427f806f..0000000000
--- a/lib/src/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 {},
-       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/lib/src/client.dart b/lib/src/client.dart
index cf1ff784a0..fd4144326f 100644
--- a/lib/src/client.dart
+++ b/lib/src/client.dart
@@ -7,10 +7,9 @@ import 'dart:convert';
 import 'dart:typed_data';
 
 import 'base_client.dart';
-import 'base_request.dart';
 import 'io_client.dart';
+import 'request.dart';
 import 'response.dart';
-import 'streamed_response.dart';
 
 /// The interface for HTTP clients that take care of maintaining persistent
 /// connections across multiple requests to the same server. If you only need to
@@ -59,7 +58,7 @@ abstract class Client {
   /// [encoding] defaults to [UTF8].
   ///
   /// For more fine-grained control over the request, use [send] instead.
-  Future<Response> post(url, {Map<String, String> headers, body,
+  Future<Response> post(url, body, {Map<String, String> headers,
       Encoding encoding});
 
   /// Sends an HTTP PUT request with the given headers and body to the given
@@ -80,7 +79,7 @@ abstract class Client {
   /// [encoding] defaults to [UTF8].
   ///
   /// For more fine-grained control over the request, use [send] instead.
-  Future<Response> put(url, {Map<String, String> headers, body,
+  Future<Response> put(url, body, {Map<String, String> headers,
       Encoding encoding});
 
   /// Sends an HTTP PATCH request with the given headers and body to the given
@@ -101,7 +100,7 @@ abstract class Client {
   /// [encoding] defaults to [UTF8].
   ///
   /// For more fine-grained control over the request, use [send] instead.
-  Future<Response> patch(url, {Map<String, String> headers, body,
+  Future<Response> patch(url, body, {Map<String, String> headers,
       Encoding encoding});
 
   /// Sends an HTTP DELETE request with the given headers to the given URL,
@@ -133,7 +132,7 @@ abstract class Client {
   Future<Uint8List> readBytes(url, {Map<String, String> headers});
 
   /// Sends an HTTP request and asynchronously returns the response.
-  Future<StreamedResponse> send(BaseRequest request);
+  Future<Response> send(Request 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
diff --git a/lib/src/request.dart b/lib/src/request.dart
index 1f2be464df..f49c5b9f16 100644
--- a/lib/src/request.dart
+++ b/lib/src/request.dart
@@ -18,7 +18,8 @@ class Request extends Message {
   /// The URL to which the request will be sent.
   final Uri url;
 
-  /// Creates a new [Request] for [url] using [method].
+  /// Creates a new [Request] for [url], which can be a [Uri] or a [String],
+  /// using [method].
   ///
   /// [body] is the request body. It may be either a [String], a [List<int>], a
   /// [Stream<List<int>>], or `null` to indicate no body. If it's a [String],
@@ -30,36 +31,37 @@ class Request extends Message {
   ///
   /// Extra [context] can be used to pass information between inner middleware
   /// and handlers.
-  Request(this.method, this.url,
+  Request(String method, url,
       {body,
       Encoding encoding,
       Map<String, String> headers,
       Map<String, Object> context})
-      : super(body, encoding: encoding, headers: headers, context: context);
+      : this._(method, getUrl(url), body, encoding, headers, context);
 
-  /// Creates a new HEAD [Request] to [url].
+  /// Creates a new HEAD [Request] to [url], which can be a [Uri] or a [String].
   ///
   /// [headers] are the HTTP headers for the request. If [headers] is `null`,
   /// it is treated as empty.
   ///
   /// Extra [context] can be used to pass information between inner middleware
   /// and handlers.
-  Request.head(Uri url,
+  Request.head(url,
       {Map<String, String> headers, Map<String, Object> context})
       : this('HEAD', url, headers: headers, context: context);
 
-  /// Creates a new GET [Request] to [url].
+  /// Creates a new GET [Request] to [url], which can be a [Uri] or a [String].
   ///
   /// [headers] are the HTTP headers for the request. If [headers] is `null`,
   /// it is treated as empty.
   ///
   /// Extra [context] can be used to pass information between inner middleware
   /// and handlers.
-  Request.get(Uri url,
+  Request.get(url,
       {Map<String, String> headers, Map<String, Object> context})
       : this('GET', url, headers: headers, context: context);
 
-  /// Creates a new POST [Request] to [url].
+  /// Creates a new POST [Request] to [url], which can be a [Uri] or a [String].
+  ///
   /// [body] is the request body. It may be either a [String], a [List<int>], a
   /// [Stream<List<int>>], or `null` to indicate no body. If it's a [String],
   /// [encoding] is used to encode it to a [Stream<List<int>>]. It defaults to
@@ -70,15 +72,14 @@ class Request extends Message {
   ///
   /// Extra [context] can be used to pass information between inner middleware
   /// and handlers.
-  Request.post(Uri url,
-      body,
+  Request.post(url, body,
       {Encoding encoding,
       Map<String, String> headers,
       Map<String, Object> context})
       : this('POST', url,
       body: body, encoding: encoding, headers: headers, context: context);
 
-  /// Creates a new PUT [Request] to [url].
+  /// Creates a new PUT [Request] to [url], which can be a [Uri] or a [String].
   ///
   /// [body] is the request body. It may be either a [String], a [List<int>], a
   /// [Stream<List<int>>], or `null` to indicate no body. If it's a [String],
@@ -90,15 +91,15 @@ class Request extends Message {
   ///
   /// Extra [context] can be used to pass information between inner middleware
   /// and handlers.
-  Request.put(Uri url,
-      body,
+  Request.put(url, body,
       {Encoding encoding,
       Map<String, String> headers,
       Map<String, Object> context})
       : this('PUT', url,
       body: body, encoding: encoding, headers: headers, context: context);
 
-  /// Creates a new PATCH [Request] to [url].
+  /// Creates a new PATCH [Request] to [url], which can be a [Uri] or a
+  /// [String].
   ///
   /// [body] is the request body. It may be either a [String], a [List<int>], a
   /// [Stream<List<int>>], or `null` to indicate no body. If it's a [String],
@@ -110,25 +111,32 @@ class Request extends Message {
   ///
   /// Extra [context] can be used to pass information between inner middleware
   /// and handlers.
-  Request.patch(Uri url,
-      body,
+  Request.patch(url, body,
       {Encoding encoding,
       Map<String, String> headers,
       Map<String, Object> context})
       : this('PATCH', url,
       body: body, encoding: encoding, headers: headers, context: context);
 
-  /// Creates a new DELETE [Request] to [url].
+  /// Creates a new DELETE [Request] to [url], which can be a [Uri] or a
+  /// [String].
   ///
   /// [headers] are the HTTP headers for the request. If [headers] is `null`,
   /// it is treated as empty.
   ///
   /// Extra [context] can be used to pass information between inner middleware
   /// and handlers.
-  Request.delete(Uri url,
+  Request.delete(url,
       {Map<String, String> headers, Map<String, Object> context})
       : this('DELETE', url, headers: headers, context: context);
 
+  Request._(this.method, this.url,
+      body,
+      Encoding encoding,
+      Map<String, String> headers,
+      Map<String, Object> context)
+      : super(body, encoding: encoding, headers: headers, context: context);
+
   /// Creates a new [Request] by copying existing values and applying specified
   /// changes.
   ///
@@ -147,10 +155,12 @@ class Request extends Message {
     var updatedHeaders = updateMap(this.headers, headers);
     var updatedContext = updateMap(this.context, context);
 
-    return new Request(this.method, this.url,
-        body: body ?? getBody(this),
-        encoding: this.encoding,
-        headers: updatedHeaders,
-        context: updatedContext);
+    return new Request._(
+        this.method,
+        this.url,
+        body ?? getBody(this),
+        this.encoding,
+        updatedHeaders,
+        updatedContext);
   }
 }
diff --git a/lib/src/streamed_request.dart b/lib/src/streamed_request.dart
deleted file mode 100644
index 6a020bd77a..0000000000
--- a/lib/src/streamed_request.dart
+++ /dev/null
@@ -1,41 +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 {
-  /// 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;
-
-  /// Creates a new streaming request.
-  StreamedRequest(String method, Uri url)
-    : _controller = new StreamController<List<int>>(sync: true),
-      super(method, url);
-
-  /// Freezes all mutable fields other than [stream] and returns a
-  /// single-subscription [ByteStream] that emits the data being written to
-  /// [sink].
-  ByteStream finalize() {
-    super.finalize();
-    return new ByteStream(_controller.stream);
-  }
-}
diff --git a/lib/src/streamed_response.dart b/lib/src/streamed_response.dart
deleted file mode 100644
index 69d8356c1d..0000000000
--- a/lib/src/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 {},
-       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/lib/src/utils.dart b/lib/src/utils.dart
index 39f1aefac4..b7e7347a3d 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -170,3 +170,16 @@ String getHeader(Map<String, String> headers, String name) {
   }
   return null;
 }
+
+/// Returns a [Uri] from the [url], which can be a [Uri] or a [String].
+///
+/// If the [url] is not a [Uri] or [String] an [ArgumentError] is thrown.
+Uri getUrl(url) {
+  if (url is Uri) {
+    return url;
+  } else if (url is String) {
+    return Uri.parse(url);
+  } else {
+    throw new ArgumentError.value(url, 'url', 'Not a Uri or String');
+  }
+}
diff --git a/pubspec.yaml b/pubspec.yaml
index 8f419adbb6..f059565133 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,10 +1,10 @@
 name: http
-version: 0.11.3+11
+version: 0.12.0-dev
 author: "Dart Team <misc@dartlang.org>"
 homepage: https://github.com/dart-lang/http
 description: A composable, Future-based API for making HTTP requests.
 dependencies:
-  async: "^1.10.0"
+  async: "^1.13.0"
   collection: "^1.5.0"
   http_parser: ">=0.0.1 <4.0.0"
   path: ">=0.9.0 <2.0.0"