blob: bbee58d2744fa5b7e7bd67b716d4745163160291 [file] [log] [blame]
// 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.
library client;
import 'dart:io';
import 'base_client.dart';
import 'base_request.dart';
import 'streamed_response.dart';
import 'utils.dart';
/// An HTTP client which takes 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], or [delete] instead.
///
/// When creating an HTTP client class with additional functionality, it's
/// recommended that you subclass [BaseClient] and wrap another instance of
/// [BaseClient] rather than subclassing [Client] directly. This allows all
/// subclasses of [BaseClient] to be mutually composable.
class Client extends BaseClient {
/// The underlying `dart:io` HTTP client.
HttpClient _inner;
/// Creates a new HTTP client.
Client() : _inner = new HttpClient();
/// Sends an HTTP request and asynchronously returns the response.
Future<StreamedResponse> send(BaseRequest request) {
var stream = request.finalize();
var completer = new Completer<StreamedResponse>();
var connection = _inner.openUrl(request.method, request.url);
connection.onError = (e) {
async.then((_) {
// TODO(nweiz): remove this when issue 4974 is fixed
if (completer.future.isComplete) throw e;
completer.completeException(e);
});
};
connection.onRequest = (underlyingRequest) {
underlyingRequest.contentLength = request.contentLength;
underlyingRequest.persistentConnection = request.persistentConnection;
request.headers.forEach((name, value) {
underlyingRequest.headers.set(name, value);
});
if (stream.closed) {
underlyingRequest.outputStream.close();
} else {
stream.pipe(underlyingRequest.outputStream);
}
};
connection.onResponse = (response) {
var headers = <String>{};
response.headers.forEach((key, value) => headers[key] = value);
completer.complete(new StreamedResponse(
response.inputStream,
response.statusCode,
response.contentLength,
headers: headers,
isRedirect: response.isRedirect,
persistentConnection: response.persistentConnection,
reasonPhrase: response.reasonPhrase));
};
return completer.future;
}
/// Closes the client. This terminates all active connections. If a client
/// remains unclosed, the Dart process may not terminate.
void close() {
if (_inner != null) _inner.shutdown();
_inner = null;
}
}