// 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.
///
/// ## Installing ##
///
/// Use [pub][] to install this package. Add the following to your
/// `pubspec.yaml` file.
///
///     dependencies:
///       http: any
///
/// Then run `pub install`.
///
/// For more information, see the
/// [http package on pub.dartlang.org](http://pub.dartlang.org/packages/http).
///
/// The easiest way to use this library is via the top-level functions. They
/// allow you to make individual HTTP requests with minimal hassle:
///
///     import 'package:http/http.dart' as http;
///
///     var url = "http://example.com/whatsit/create";
///     http.post(url, fields: {"name": "doodle", "color": "blue"})
///         .then((response) {
///       print("Response status: ${response.statusCode}");
///       print("Response body: ${response.body}");
///     });
///
///     http.read("http://example.com/foobar.txt").then(print);
///
/// If you're making multiple requests to the same server, you can keep open a
/// persistent connection by using a [Client] rather than making one-off
/// requests. If you do this, make sure to close the client when you're done:
///
///     var client = new http.Client();
///     client.post(
///         "http://example.com/whatsit/create",
///         fields: {"name": "doodle", "color": "blue"})
///       .then((response) => client.get(response.bodyFields['uri']))
///       .then((response) => print(response.body))
///       .whenComplete(client.close);
///
/// You can also exert more fine-grained control over your requests and
/// responses by creating [Request] or [StreamedRequest] objects yourself and
/// passing them to [Client.send].
///
/// This package is designed to be composable. This makes it easy for external
/// libraries to work with one another to add behavior to it. Libraries wishing
/// to add behavior should create a subclass of [BaseClient] that wraps another
/// [Client] and adds the desired behavior:
///
///     class UserAgentClient extends http.BaseClient {
///       final String userAgent;
///       final http.Client _inner;
///
///       UserAgentClient(this.userAgent, this._inner);
///
///       Future<StreamedResponse> send(BaseRequest request) {
///         request.headers[HttpHeaders.USER_AGENT] = userAgent;
///         return _inner.send(request);
///       }
///     }
///
/// [pub]: http://pub.dartlang.org
library http;

import 'dart:async';
import 'dart:typed_data';

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/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].
///
/// 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(url, {Map<String, String> headers}) =>
  _withClient((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(url, {Map<String, String> headers}) =>
  _withClient((client) => client.get(url, headers: headers));

/// Sends an HTTP POST request with the given headers and fields to the given
/// URL, which an be a [Uri] or a [String]. If any fields are specified, the
/// content-type is automatically set to `"application/x-www-form-urlencoded"`.
///
/// 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] or
/// [StreamedRequest] instead.
Future<Response> post(url,
    {Map<String, String> headers,
     Map<String, String> fields}) =>
  _withClient((client) => client.post(url, headers: headers, fields: fields));

/// Sends an HTTP POST request with the given headers and fields to the given
/// URL, which can be a [Uri] or a [String]. If any fields are specified, the
/// content-type is automatically set to `"application/x-www-form-urlencoded"`.
///
/// 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] or
/// [StreamedRequest] instead.
Future<Response> put(url,
    {Map<String, String> headers,
     Map<String, String> fields}) =>
  _withClient((client) => client.put(url, headers: headers, fields: fields));

/// 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(url, {Map<String, String> headers}) =>
  _withClient((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 an [HttpException] 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(url, {Map<String, String> headers}) =>
  _withClient((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 an [HttpException] 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(url, {Map<String, String> headers}) =>
  _withClient((client) => client.readBytes(url, headers: headers));

Future _withClient(Future fn(Client)) {
  var client = new Client();
  var future = fn(client);
  return future.whenComplete(client.close);
}
