Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 /// A composable, [Future]-based library for making HTTP requests. | 5 /// A composable, [Future]-based library for making HTTP requests. |
| 6 /// | 6 /// |
| 7 /// ## Installing ## | 7 /// ## Installing ## |
| 8 /// | 8 /// |
| 9 /// Use [pub][] to install this package. Add the following to your | 9 /// Use [pub][] to install this package. Add the following to your |
| 10 /// `pubspec.yaml` file. | 10 /// `pubspec.yaml` file. |
| 11 /// | 11 /// |
| 12 /// dependencies: | 12 /// dependencies: |
| 13 /// http: any | 13 /// http: any |
| 14 /// | 14 /// |
| 15 /// Then run `pub install`. | 15 /// Then run `pub install`. |
| 16 /// | 16 /// |
| 17 /// For more information, see the | 17 /// For more information, see the |
| 18 /// [http package on pub.dartlang.org](http://pub.dartlang.org/packages/http). | 18 /// [http package on pub.dartlang.org](http://pub.dartlang.org/packages/http). |
| 19 /// | 19 /// |
| 20 /// The easiest way to use this library is via the top-level functions. They | 20 /// The easiest way to use this library is via the top-level functions. They |
| 21 /// allow you to make individual HTTP requests with minimal hassle: | 21 /// allow you to make individual HTTP requests with minimal hassle: |
| 22 /// | 22 /// |
| 23 /// import 'package:http/http.dart' as http; | 23 /// import 'package:http/http.dart' as http; |
| 24 /// | 24 /// |
| 25 /// var url = "http://example.com/whatsit/create"; | 25 /// var url = "http://example.com/whatsit/create"; |
| 26 /// http.post(url, fields: {"name": "doodle", "color": "blue"}) | 26 /// http.post(url, body: {"name": "doodle", "color": "blue"}) |
| 27 /// .then((response) { | 27 /// .then((response) { |
| 28 /// print("Response status: ${response.statusCode}"); | 28 /// print("Response status: ${response.statusCode}"); |
| 29 /// print("Response body: ${response.body}"); | 29 /// print("Response body: ${response.body}"); |
| 30 /// }); | 30 /// }); |
| 31 /// | 31 /// |
| 32 /// http.read("http://example.com/foobar.txt").then(print); | 32 /// http.read("http://example.com/foobar.txt").then(print); |
| 33 /// | 33 /// |
| 34 /// If you're making multiple requests to the same server, you can keep open a | 34 /// If you're making multiple requests to the same server, you can keep open a |
| 35 /// persistent connection by using a [Client] rather than making one-off | 35 /// persistent connection by using a [Client] rather than making one-off |
| 36 /// requests. If you do this, make sure to close the client when you're done: | 36 /// requests. If you do this, make sure to close the client when you're done: |
| 37 /// | 37 /// |
| 38 /// var client = new http.Client(); | 38 /// var client = new http.Client(); |
| 39 /// client.post( | 39 /// client.post( |
| 40 /// "http://example.com/whatsit/create", | 40 /// "http://example.com/whatsit/create", |
| 41 /// fields: {"name": "doodle", "color": "blue"}) | 41 /// body: {"name": "doodle", "color": "blue"}) |
| 42 /// .then((response) => client.get(response.bodyFields['uri'])) | 42 /// .then((response) => client.get(response.bodyFields['uri'])) |
| 43 /// .then((response) => print(response.body)) | 43 /// .then((response) => print(response.body)) |
| 44 /// .whenComplete(client.close); | 44 /// .whenComplete(client.close); |
| 45 /// | 45 /// |
| 46 /// You can also exert more fine-grained control over your requests and | 46 /// You can also exert more fine-grained control over your requests and |
| 47 /// responses by creating [Request] or [StreamedRequest] objects yourself and | 47 /// responses by creating [Request] or [StreamedRequest] objects yourself and |
| 48 /// passing them to [Client.send]. | 48 /// passing them to [Client.send]. |
| 49 /// | 49 /// |
| 50 /// This package is designed to be composable. This makes it easy for external | 50 /// This package is designed to be composable. This makes it easy for external |
| 51 /// libraries to work with one another to add behavior to it. Libraries wishing | 51 /// libraries to work with one another to add behavior to it. Libraries wishing |
| 52 /// to add behavior should create a subclass of [BaseClient] that wraps another | 52 /// to add behavior should create a subclass of [BaseClient] that wraps another |
| 53 /// [Client] and adds the desired behavior: | 53 /// [Client] and adds the desired behavior: |
| 54 /// | 54 /// |
| 55 /// class UserAgentClient extends http.BaseClient { | 55 /// class UserAgentClient extends http.BaseClient { |
| 56 /// final String userAgent; | 56 /// final String userAgent; |
| 57 /// final http.Client _inner; | 57 /// final http.Client _inner; |
| 58 /// | 58 /// |
| 59 /// UserAgentClient(this.userAgent, this._inner); | 59 /// UserAgentClient(this.userAgent, this._inner); |
| 60 /// | 60 /// |
| 61 /// Future<StreamedResponse> send(BaseRequest request) { | 61 /// Future<StreamedResponse> send(BaseRequest request) { |
| 62 /// request.headers[HttpHeaders.USER_AGENT] = userAgent; | 62 /// request.headers[HttpHeaders.USER_AGENT] = userAgent; |
| 63 /// return _inner.send(request); | 63 /// return _inner.send(request); |
| 64 /// } | 64 /// } |
| 65 /// } | 65 /// } |
| 66 /// | 66 /// |
| 67 /// [pub]: http://pub.dartlang.org | 67 /// [pub]: http://pub.dartlang.org |
| 68 library http; | 68 library http; |
| 69 | 69 |
| 70 import 'dart:async'; | 70 import 'dart:async'; |
| 71 import 'dart:convert'; | |
| 71 import 'dart:typed_data'; | 72 import 'dart:typed_data'; |
| 72 | 73 |
| 73 import 'src/client.dart'; | 74 import 'src/client.dart'; |
| 74 import 'src/response.dart'; | 75 import 'src/response.dart'; |
| 75 | 76 |
| 76 export 'src/base_client.dart'; | 77 export 'src/base_client.dart'; |
| 77 export 'src/base_request.dart'; | 78 export 'src/base_request.dart'; |
| 78 export 'src/base_response.dart'; | 79 export 'src/base_response.dart'; |
| 79 export 'src/byte_stream.dart'; | 80 export 'src/byte_stream.dart'; |
| 80 export 'src/client.dart'; | 81 export 'src/client.dart'; |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 100 /// be a [Uri] or a [String]. | 101 /// be a [Uri] or a [String]. |
| 101 /// | 102 /// |
| 102 /// This automatically initializes a new [Client] and closes that client once | 103 /// This automatically initializes a new [Client] and closes that client once |
| 103 /// the request is complete. If you're planning on making multiple requests to | 104 /// the request is complete. If you're planning on making multiple requests to |
| 104 /// the same server, you should use a single [Client] for all of those requests. | 105 /// the same server, you should use a single [Client] for all of those requests. |
| 105 /// | 106 /// |
| 106 /// For more fine-grained control over the request, use [Request] instead. | 107 /// For more fine-grained control over the request, use [Request] instead. |
| 107 Future<Response> get(url, {Map<String, String> headers}) => | 108 Future<Response> get(url, {Map<String, String> headers}) => |
| 108 _withClient((client) => client.get(url, headers: headers)); | 109 _withClient((client) => client.get(url, headers: headers)); |
| 109 | 110 |
| 110 /// Sends an HTTP POST request with the given headers and fields to the given | 111 /// Sends an HTTP POST request with the given headers and body to the given URL, |
| 111 /// URL, which an be a [Uri] or a [String]. If any fields are specified, the | 112 /// which can be a [Uri] or a [String]. |
| 112 /// content-type is automatically set to `"application/x-www-form-urlencoded"`. | |
| 113 /// | 113 /// |
| 114 /// This automatically initializes a new [Client] and closes that client once | 114 /// [body] sets the body of the request. It can be a [String], a [List<int>] or |
| 115 /// the request is complete. If you're planning on making multiple requests to | 115 /// a [Map<String, String>]. If it's a String, it's encoded using [encoding] and |
| 116 /// the same server, you should use a single [Client] for all of those requests. | 116 /// used as the body of the request. The content-type of the request will |
| 117 /// default to "text/plain". | |
| 118 /// | |
| 119 /// If [body] is a List, it's used as-is as the body of the request. | |
|
Bob Nystrom
2013/11/12 00:07:33
Instead of "used as-is" how about clarifying that
nweiz
2013/11/12 01:59:13
Done.
| |
| 120 /// | |
| 121 /// If [body] is a Map, it's encoded as form fields using [encoding]. The | |
| 122 /// content-type of the request will be set to | |
| 123 /// `"application/x-www-form-urlencoded"`; this cannot be overridden. | |
| 124 /// | |
| 125 /// [encoding] defaults to [UTF8]. | |
| 117 /// | 126 /// |
| 118 /// For more fine-grained control over the request, use [Request] or | 127 /// For more fine-grained control over the request, use [Request] or |
| 119 /// [StreamedRequest] instead. | 128 /// [StreamedRequest] instead. |
| 120 Future<Response> post(url, | 129 Future<Response> post(url, {Map<String, String> headers, body, |
| 121 {Map<String, String> headers, | 130 Encoding encoding}) => |
| 122 Map<String, String> fields}) => | 131 _withClient((client) => client.post(url, |
| 123 _withClient((client) => client.post(url, headers: headers, fields: fields)); | 132 headers: headers, body: body, encoding: encoding)); |
| 124 | 133 |
| 125 /// Sends an HTTP POST request with the given headers and fields to the given | 134 /// Sends an HTTP PUT request with the given headers and body to the given URL, |
| 126 /// URL, which can be a [Uri] or a [String]. If any fields are specified, the | 135 /// which can be a [Uri] or a [String]. |
| 127 /// content-type is automatically set to `"application/x-www-form-urlencoded"`. | |
| 128 /// | 136 /// |
| 129 /// This automatically initializes a new [Client] and closes that client once | 137 /// [body] sets the body of the request. It can be a [String], a [List<int>] or |
| 130 /// the request is complete. If you're planning on making multiple requests to | 138 /// a [Map<String, String>]. If it's a String, it's encoded using [encoding] and |
| 131 /// the same server, you should use a single [Client] for all of those requests. | 139 /// used as the body of the request. The content-type of the request will |
| 140 /// default to "text/plain". | |
| 141 /// | |
| 142 /// If [body] is a List, it's used as-is as the body of the request. | |
| 143 /// | |
| 144 /// If [body] is a Map, it's encoded as form fields using [encoding]. The | |
| 145 /// content-type of the request will be set to | |
| 146 /// `"application/x-www-form-urlencoded"`; this cannot be overridden. | |
| 147 /// | |
| 148 /// [encoding] defaults to [UTF8]. | |
| 132 /// | 149 /// |
| 133 /// For more fine-grained control over the request, use [Request] or | 150 /// For more fine-grained control over the request, use [Request] or |
| 134 /// [StreamedRequest] instead. | 151 /// [StreamedRequest] instead. |
| 135 Future<Response> put(url, | 152 Future<Response> put(url, {Map<String, String> headers, body, |
| 136 {Map<String, String> headers, | 153 Encoding encoding}) => |
| 137 Map<String, String> fields}) => | 154 _withClient((client) => client.put(url, |
| 138 _withClient((client) => client.put(url, headers: headers, fields: fields)); | 155 headers: headers, body: body, encoding: encoding)); |
| 139 | 156 |
| 140 /// Sends an HTTP DELETE request with the given headers to the given URL, which | 157 /// Sends an HTTP DELETE request with the given headers to the given URL, which |
| 141 /// can be a [Uri] or a [String]. | 158 /// can be a [Uri] or a [String]. |
| 142 /// | 159 /// |
| 143 /// This automatically initializes a new [Client] and closes that client once | 160 /// This automatically initializes a new [Client] and closes that client once |
| 144 /// the request is complete. If you're planning on making multiple requests to | 161 /// the request is complete. If you're planning on making multiple requests to |
| 145 /// the same server, you should use a single [Client] for all of those requests. | 162 /// the same server, you should use a single [Client] for all of those requests. |
| 146 /// | 163 /// |
| 147 /// For more fine-grained control over the request, use [Request] instead. | 164 /// For more fine-grained control over the request, use [Request] instead. |
| 148 Future<Response> delete(url, {Map<String, String> headers}) => | 165 Future<Response> delete(url, {Map<String, String> headers}) => |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 178 /// For more fine-grained control over the request and response, use [Request] | 195 /// For more fine-grained control over the request and response, use [Request] |
| 179 /// instead. | 196 /// instead. |
| 180 Future<Uint8List> readBytes(url, {Map<String, String> headers}) => | 197 Future<Uint8List> readBytes(url, {Map<String, String> headers}) => |
| 181 _withClient((client) => client.readBytes(url, headers: headers)); | 198 _withClient((client) => client.readBytes(url, headers: headers)); |
| 182 | 199 |
| 183 Future _withClient(Future fn(Client)) { | 200 Future _withClient(Future fn(Client)) { |
| 184 var client = new Client(); | 201 var client = new Client(); |
| 185 var future = fn(client); | 202 var future = fn(client); |
| 186 return future.whenComplete(client.close); | 203 return future.whenComplete(client.close); |
| 187 } | 204 } |
| OLD | NEW |