Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 library base_request; | |
| 6 | |
| 7 import 'dart:io'; | |
| 8 import 'dart:uri'; | |
| 9 | |
| 10 import 'client.dart'; | |
| 11 import 'stream_response.dart'; | |
| 12 | |
| 13 /// The base class for HTTP requests. | |
| 14 /// | |
| 15 /// Subclasses of [BaseRequest] can be constructed manually and passed to | |
| 16 /// [BaseClient.send], which allows the user to provide fine-grained control | |
| 17 /// over the request properties. However, usually it's easier to use convenience | |
| 18 /// methods like [get] or [BaseClient.get]. | |
| 19 abstract class BaseRequest { | |
| 20 /// The HTTP method of the request. Most commonly "GET" or "POST", less | |
| 21 /// commonly "HEAD", "PUT", or "DELETE". Non-standard method names are also | |
| 22 /// supported. | |
| 23 final String method; | |
| 24 | |
| 25 /// 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.
| |
| 26 final Uri url; | |
| 27 | |
| 28 /// 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
| |
| 29 /// indicates that the size of the request is not known in advance. | |
| 30 int get contentLength => _contentLength; | |
| 31 int _contentLength = -1; | |
| 32 | |
| 33 set contentLength(int value) { | |
| 34 _checkFinalized(); | |
| 35 _contentLength = value; | |
| 36 } | |
| 37 | |
| 38 /// Whether a persistent connection should be maintained with the server. | |
| 39 /// Defaults to true. | |
| 40 bool get persistentConnection => _persistentConnection; | |
| 41 bool _persistentConnection = true; | |
| 42 | |
| 43 set persistentConnection(bool value) { | |
| 44 _checkFinalized(); | |
| 45 _persistentConnection = value; | |
| 46 } | |
| 47 | |
| 48 /// Whether the client should follow redirects while resolving this request. | |
| 49 /// Defaults to true. | |
| 50 bool get followRedirects => _followRedirects; | |
| 51 bool _followRedirects = true; | |
| 52 | |
| 53 set followRedirects(bool value) { | |
| 54 _checkFinalized(); | |
| 55 _followRedirects = value; | |
| 56 } | |
| 57 | |
| 58 /// The maximum number of redirects to follow when [followRedirects] is true. | |
| 59 /// If this number is exceeded the [BaseResponse] future will signal a | |
| 60 /// [RedirectLimitExceeded] exception. Defaults to 5. | |
| 61 int get maxRedirects => _maxRedirects; | |
| 62 int _maxRedirects = 5; | |
| 63 | |
| 64 set maxRedirects(int value) { | |
| 65 _checkFinalized(); | |
| 66 _maxRedirects = value; | |
| 67 } | |
| 68 | |
| 69 // TODO(nweiz): automatically parse cookies from headers | |
| 70 | |
| 71 // TODO(nweiz): make this a HttpHeaders object | |
| 72 /// The headers for this request. | |
| 73 final Map<String, String> headers; | |
| 74 | |
| 75 /// Whether the request has been finalized. | |
| 76 bool get finalized => _finalized; | |
| 77 bool _finalized = false; | |
| 78 | |
| 79 /// Create a new HTTP request. | |
| 80 /// | |
| 81 /// 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.
| |
| 82 BaseRequest(this.method, this.url) | |
| 83 : headers = <String>{}; | |
| 84 | |
| 85 /// Finalizes the HTTP request in preparation for it being sent. This freezes | |
| 86 /// all mutable fields and returns an [InputStream] that should emit the body | |
| 87 /// of the request. The stream may be closed to indicate a request with no | |
| 88 /// body. | |
| 89 /// | |
| 90 /// The base implementation of this returns null rather than an [InputStream]; | |
| 91 /// subclasses are responsible for creating the return value. They should also | |
| 92 /// freeze any additional mutable fields they add that don't make sense to | |
| 93 /// change after the request headers are sent. | |
| 94 InputStream finalize() { | |
| 95 // TODO(nweiz): freeze headers | |
| 96 if (finalized) throw new StateError("Can't finalize a finalized Request."); | |
| 97 _finalized = true; | |
| 98 return null; | |
| 99 } | |
| 100 | |
| 101 /// Send this request. | |
| 102 /// | |
| 103 /// This automatically initializes a new [Client] and closes that client once | |
| 104 /// the request is complete. If you're planning on making multiple requests to | |
| 105 /// the same server, you should use a single [Client] for all of those | |
| 106 /// requests. | |
| 107 Future<StreamResponse> send() { | |
| 108 var client = new Client(); | |
| 109 var future = client.send(this); | |
| 110 future.onComplete((_) => client.close()); | |
| 111 return future; | |
| 112 } | |
| 113 | |
| 114 /// Throw an error if this request has been finalized. | |
| 115 void _checkFinalized() { | |
| 116 if (!finalized) return; | |
| 117 throw new StateError("Can't modify a finalized Request."); | |
| 118 } | |
| 119 } | |
| OLD | NEW |