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 |