Chromium Code Reviews| Index: pkg/http/lib/src/base_request.dart |
| diff --git a/pkg/http/lib/src/base_request.dart b/pkg/http/lib/src/base_request.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..fb09472bb3319cc4144cdcb56619301ee105ab03 |
| --- /dev/null |
| +++ b/pkg/http/lib/src/base_request.dart |
| @@ -0,0 +1,119 @@ |
| +// 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 base_request; |
| + |
| +import 'dart:io'; |
| +import 'dart:uri'; |
| + |
| +import 'client.dart'; |
| +import 'stream_response.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 request will be sent. |
|
Bob Nystrom
2012/10/31 01:17:44
"which request" -> "which the request".
nweiz
2012/10/31 18:20:59
Done.
|
| + final Uri url; |
| + |
| + /// The size of the request body, in bytes. This defaults to -1, which |
|
Bob Nystrom
2012/10/31 01:17:44
Style nit. What do you think of putting literals l
nweiz
2012/10/31 18:20:59
Dislike. I think it makes the docstring harder to
|
| + /// indicates that the size of the request is not known in advance. |
| + int get contentLength => _contentLength; |
| + int _contentLength = -1; |
| + |
| + set contentLength(int 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 |
| + /// [RedirectLimitExceeded] exception. 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; |
| + |
| + /// Create a new HTTP request. |
| + /// |
| + /// This should not be called directly. Only subclasses should be constructed. |
|
Bob Nystrom
2012/10/31 01:17:44
It's a dynamic error now to try to instantiate an
nweiz
2012/10/31 18:20:59
Sweet.
|
| + BaseRequest(this.method, this.url) |
| + : headers = <String>{}; |
| + |
| + /// Finalizes the HTTP request in preparation for it being sent. This freezes |
| + /// all mutable fields and returns an [InputStream] that should emit the body |
| + /// of the request. The stream may be closed to indicate a request with no |
| + /// body. |
| + /// |
| + /// The base implementation of this returns null rather than an [InputStream]; |
| + /// subclasses are responsible for creating the return value. They should also |
| + /// freeze any additional mutable fields they add that don't make sense to |
| + /// change after the request headers are sent. |
| + InputStream finalize() { |
| + // TODO(nweiz): freeze headers |
| + if (finalized) throw new StateError("Can't finalize a finalized Request."); |
| + _finalized = true; |
| + return null; |
| + } |
| + |
| + /// Send 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<StreamResponse> send() { |
| + var client = new Client(); |
| + var future = client.send(this); |
| + future.onComplete((_) => client.close()); |
| + return future; |
| + } |
| + |
| + /// Throw an error if this request has been finalized. |
| + void _checkFinalized() { |
| + if (!finalized) return; |
| + throw new StateError("Can't modify a finalized Request."); |
| + } |
| +} |