| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 part of dart.io; | |
| 6 | |
| 7 | |
| 8 /** | |
| 9 * [HttpBodyHandler] is a helper class for processing and collecting | |
| 10 * HTTP message data in an easy-to-use [HttpBody] object. The content | |
| 11 * body is parsed, depending on the `Content-Type` header field. When | |
| 12 * the full body is read and parsed the body content is made | |
| 13 * available. The class can be used to process both server requests | |
| 14 * and client responses. | |
| 15 * | |
| 16 * The following content types are recognized: | |
| 17 * | |
| 18 * text/\* | |
| 19 * application/json | |
| 20 * application/x-www-form-urlencoded | |
| 21 * multipart/form-data | |
| 22 * | |
| 23 * For content type `text/\*` the body is decoded into a string. The | |
| 24 * 'charset' parameter of the content type specifies the encoding | |
| 25 * used for decoding. If no 'charset' is present the default encoding | |
| 26 * of ISO-8859-1 is used. | |
| 27 * | |
| 28 * For content type `application/json` the body is decoded into a | |
| 29 * string which is then parsed as JSON. The resulting body is a | |
| 30 * [Map]. The 'charset' parameter of the content type specifies the | |
| 31 * encoding used for decoding. If no 'charset' is present the default | |
| 32 * encoding of UTF-8 is used. | |
| 33 * | |
| 34 * For content type `application/x-www-form-urlencoded` the body is a | |
| 35 * query string which is then split according to the rules for | |
| 36 * splitting a query string. The resulting body is a `Map<String, | |
| 37 * String>`. If the same name is present several times in the query | |
| 38 * string, then the last value seen for this name will be in the | |
| 39 * resulting map. The encoding US-ASCII is always used for decoding | |
| 40 * the body. | |
| 41 * | |
| 42 * For content type `multipart/form-data` the body is parsed into | |
| 43 * it's different fields. The resulting body is a `Map<String, | |
| 44 * dynamic>`, where the value is a [String] for normal fields and a | |
| 45 * [HttpBodyFileUpload] instance for file upload fields. If the same | |
| 46 * name is present several times, then the last value seen for this | |
| 47 * name will be in the resulting map. | |
| 48 * | |
| 49 * When using content type `multipart/form-data` the encoding of | |
| 50 * fields with [String] values is determined by the browser sending | |
| 51 * the HTTP request with the form data. The encoding is specified | |
| 52 * either by the attribute `accept-charset` on the HTML form, or by | |
| 53 * the content type of the web page containing the form. If the HTML | |
| 54 * form has an `accept-charset` attribute the browser will use the | |
| 55 * encoding specified there. If the HTML form has no `accept-charset` | |
| 56 * attribute the browser determines the encoding from the content | |
| 57 * type of the web page containing the form. Using a content type of | |
| 58 * `text/html; charset=utf-8` for the page and setting | |
| 59 * `accept-charset` on the HTML form to `utf-8` is recommended as the | |
| 60 * default for [HttpBodyHandler] is UTF-8. It is important to get | |
| 61 * these encoding values right, as the actual `multipart/form-data` | |
| 62 * HTTP request sent by the browser does _not_ contain any | |
| 63 * information on the encoding. If something else than UTF-8 is used | |
| 64 * `defaultEncoding` needs to be set in the [HttpBodyHandler] | |
| 65 * constructor and calls to [processRequest] and [processResponse]. | |
| 66 * | |
| 67 * For all other content types the body will be treated as | |
| 68 * uninterpreted binary data. The resulting body will be of type | |
| 69 * `List<int>`. | |
| 70 * | |
| 71 * To use with the [HttpServer] for request messages, [HttpBodyHandler] can be | |
| 72 * used as either a [StreamTransformer] or as a per-request handler (see | |
| 73 * [processRequest]). | |
| 74 * | |
| 75 * HttpServer server = ... | |
| 76 * server.transform(new HttpBodyHandler()) | |
| 77 * .listen((HttpRequestBody body) { | |
| 78 * ... | |
| 79 * }); | |
| 80 * | |
| 81 * To use with the [HttpClient] for response messages, [HttpBodyHandler] can be | |
| 82 * used as a per-request handler (see [processResponse]). | |
| 83 * | |
| 84 * HttpClient client = ... | |
| 85 * client.get(...) | |
| 86 * .then((HttpClientRequest response) => response.close()) | |
| 87 * .then(HttpBodyHandler.processResponse) | |
| 88 * .then((HttpClientResponseBody body) { | |
| 89 * ... | |
| 90 * }); | |
| 91 * | |
| 92 */ | |
| 93 class HttpBodyHandler | |
| 94 implements StreamTransformer<HttpRequest, HttpRequestBody> { | |
| 95 var _transformer; | |
| 96 | |
| 97 /** | |
| 98 * Create a new [HttpBodyHandler] to be used with a [Stream]<[HttpRequest]>, | |
| 99 * e.g. a [HttpServer]. | |
| 100 * | |
| 101 * If the page is served using different encoding than UTF-8, set | |
| 102 * [defaultEncoding] accordingly. This is required for parsing | |
| 103 * `multipart/form-data` content correctly. See the class comment | |
| 104 * for more information on `multipart/form-data`. | |
| 105 */ | |
| 106 HttpBodyHandler({Encoding defaultEncoding: Encoding.UTF_8}) | |
| 107 : _transformer = new _HttpBodyHandlerTransformer(defaultEncoding); | |
| 108 | |
| 109 /** | |
| 110 * Process and parse an incoming [HttpRequest]. The returned [HttpRequestBody] | |
| 111 * contains a [response] field for accessing the [HttpResponse]. | |
| 112 * | |
| 113 * See [HttpBodyHandler] constructor for more info on [defaultEncoding]. | |
| 114 */ | |
| 115 static Future<HttpRequestBody> processRequest( | |
| 116 HttpRequest request, | |
| 117 {Encoding defaultEncoding: Encoding.UTF_8}) { | |
| 118 return _HttpBodyHandler.processRequest(request, defaultEncoding); | |
| 119 } | |
| 120 | |
| 121 /** | |
| 122 * Process and parse an incoming [HttpClientResponse]. | |
| 123 * | |
| 124 * See [HttpBodyHandler] constructor for more info on [defaultEncoding]. | |
| 125 */ | |
| 126 static Future<HttpClientResponseBody> processResponse( | |
| 127 HttpClientResponse response, | |
| 128 {Encoding defaultEncoding: Encoding.UTF_8}) { | |
| 129 return _HttpBodyHandler.processResponse(response, defaultEncoding); | |
| 130 } | |
| 131 | |
| 132 Stream<HttpRequestBody> bind(Stream<HttpRequest> stream) { | |
| 133 return _transformer.bind(stream); | |
| 134 } | |
| 135 } | |
| 136 | |
| 137 | |
| 138 /** | |
| 139 * A HTTP content body produced by [HttpBodyHandler] for either [HttpRequest] | |
| 140 * or [HttpClientResponse]. | |
| 141 */ | |
| 142 abstract class HttpBody { | |
| 143 /** | |
| 144 * The content type e.g. application/json, application/octet-stream, | |
| 145 * application/x-www-form-urlencoded, text/plain. | |
| 146 */ | |
| 147 ContentType get contentType; | |
| 148 | |
| 149 /** | |
| 150 * A high-level type value, that reflects how the body was parsed, e.g. | |
| 151 * "text", "binary" and "json". | |
| 152 */ | |
| 153 String get type; | |
| 154 | |
| 155 /** | |
| 156 * The actual body. The type depends on [type]. | |
| 157 */ | |
| 158 dynamic get body; | |
| 159 } | |
| 160 | |
| 161 | |
| 162 /** | |
| 163 * The [HttpBody] of a [HttpClientResponse] will be of type | |
| 164 * [HttpClientResponseBody]. It contains the [HttpClientResponse] object | |
| 165 * for access to the headers. | |
| 166 */ | |
| 167 abstract class HttpClientResponseBody extends HttpBody { | |
| 168 /** | |
| 169 * Returns the status code. | |
| 170 */ | |
| 171 int get statusCode; | |
| 172 | |
| 173 /** | |
| 174 * Returns the reason phrase associated with the status code. | |
| 175 */ | |
| 176 String get reasonPhrase; | |
| 177 | |
| 178 /** | |
| 179 * Returns the response headers. | |
| 180 */ | |
| 181 HttpHeaders get headers; | |
| 182 | |
| 183 /** | |
| 184 * The [HttpClientResponse] of the HTTP body. | |
| 185 */ | |
| 186 HttpClientResponse get response; | |
| 187 } | |
| 188 | |
| 189 | |
| 190 /** | |
| 191 * The [HttpBody] of a [HttpRequest] will be of type [HttpRequestBody]. It | |
| 192 * contains the fields used to read all request header information and | |
| 193 * responding to the client. | |
| 194 */ | |
| 195 abstract class HttpRequestBody extends HttpBody { | |
| 196 /** | |
| 197 * Returns the method for the request. | |
| 198 */ | |
| 199 String get method; | |
| 200 | |
| 201 /** | |
| 202 * Returns the URI for the request. | |
| 203 */ | |
| 204 Uri get uri; | |
| 205 | |
| 206 /** | |
| 207 * Returns the request headers. | |
| 208 */ | |
| 209 HttpHeaders get headers; | |
| 210 | |
| 211 /** | |
| 212 * The [HttpResponse] used for responding to the client. | |
| 213 */ | |
| 214 HttpResponse get response; | |
| 215 } | |
| 216 | |
| 217 | |
| 218 /** | |
| 219 * A [HttpBodyFileUpload] object wraps a file upload, presenting a way for | |
| 220 * extracting filename, contentType and the data of the uploaded file. | |
| 221 */ | |
| 222 abstract class HttpBodyFileUpload { | |
| 223 /** | |
| 224 * The filename of the uploaded file. | |
| 225 */ | |
| 226 String filename; | |
| 227 | |
| 228 /** | |
| 229 * The [ContentType] of the uploaded file. For 'text/\*' and | |
| 230 * 'application/json' the [data] field will a String. | |
| 231 */ | |
| 232 ContentType contentType; | |
| 233 | |
| 234 /** | |
| 235 * The content of the file. Either a [String] or a [List<int>]. | |
| 236 */ | |
| 237 dynamic content; | |
| 238 } | |
| OLD | NEW |