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 library multipart_test; | 5 library multipart_test; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:convert'; | 8 import 'dart:convert'; |
9 import 'dart:io'; | 9 import 'dart:io'; |
10 | 10 |
11 import 'package:http/http.dart' as http; | 11 import 'package:http/http.dart' as http; |
| 12 import 'package:http_parser/http_parser.dart'; |
12 import 'package:path/path.dart' as path; | 13 import 'package:path/path.dart' as path; |
13 import 'package:unittest/unittest.dart'; | 14 import 'package:unittest/unittest.dart'; |
14 | 15 |
15 import 'utils.dart'; | 16 import 'utils.dart'; |
16 | 17 |
17 /// A matcher that validates the body of a multipart request after finalization. | 18 /// A matcher that validates the body of a multipart request after finalization. |
18 /// The string "{{boundary}}" in [pattern] will be replaced by the boundary | 19 /// The string "{{boundary}}" in [pattern] will be replaced by the boundary |
19 /// string for the request, and LF newlines will be replaced with CRLF. | 20 /// string for the request, and LF newlines will be replaced with CRLF. |
20 /// Indentation will be normalized. | 21 /// Indentation will be normalized. |
21 Matcher bodyMatches(String pattern) => new _BodyMatches(pattern); | 22 Matcher bodyMatches(String pattern) => new _BodyMatches(pattern); |
22 | 23 |
23 class _BodyMatches extends Matcher { | 24 class _BodyMatches extends Matcher { |
24 final String _pattern; | 25 final String _pattern; |
25 | 26 |
26 _BodyMatches(this._pattern); | 27 _BodyMatches(this._pattern); |
27 | 28 |
28 bool matches(item, Map matchState) { | 29 bool matches(item, Map matchState) { |
29 if (item is! http.MultipartRequest) return false; | 30 if (item is! http.MultipartRequest) return false; |
30 | 31 |
31 var future = item.finalize().toBytes().then((bodyBytes) { | 32 var future = item.finalize().toBytes().then((bodyBytes) { |
32 var body = UTF8.decode(bodyBytes); | 33 var body = UTF8.decode(bodyBytes); |
33 var contentType = ContentType.parse(item.headers['content-type']); | 34 var contentType = new MediaType.parse(item.headers['content-type']); |
34 var boundary = contentType.parameters['boundary']; | 35 var boundary = contentType.parameters['boundary']; |
35 var expected = cleanUpLiteral(_pattern) | 36 var expected = cleanUpLiteral(_pattern) |
36 .replaceAll("\n", "\r\n") | 37 .replaceAll("\n", "\r\n") |
37 .replaceAll("{{boundary}}", boundary); | 38 .replaceAll("{{boundary}}", boundary); |
38 | 39 |
39 expect(body, equals(expected)); | 40 expect(body, equals(expected)); |
40 expect(item.contentLength, equals(bodyBytes.length)); | 41 expect(item.contentLength, equals(bodyBytes.length)); |
41 }); | 42 }); |
42 | 43 |
43 return completes.matches(future, matchState); | 44 return completes.matches(future, matchState); |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 content-disposition: form-data; name="file"; filename="foo%22bar" | 182 content-disposition: form-data; name="file"; filename="foo%22bar" |
182 | 183 |
183 contents | 184 contents |
184 --{{boundary}}-- | 185 --{{boundary}}-- |
185 ''')); | 186 ''')); |
186 }); | 187 }); |
187 | 188 |
188 test('with a string file with a content-type but no charset', () { | 189 test('with a string file with a content-type but no charset', () { |
189 var request = new http.MultipartRequest('POST', dummyUrl); | 190 var request = new http.MultipartRequest('POST', dummyUrl); |
190 var file = new http.MultipartFile.fromString('file', '{"hello": "world"}', | 191 var file = new http.MultipartFile.fromString('file', '{"hello": "world"}', |
191 contentType: new ContentType('application', 'json')); | 192 contentType: new MediaType('application', 'json')); |
192 request.files.add(file); | 193 request.files.add(file); |
193 | 194 |
194 expect(request, bodyMatches(''' | 195 expect(request, bodyMatches(''' |
195 --{{boundary}} | 196 --{{boundary}} |
196 content-type: application/json; charset=utf-8 | 197 content-type: application/json; charset=utf-8 |
197 content-disposition: form-data; name="file" | 198 content-disposition: form-data; name="file" |
198 | 199 |
199 {"hello": "world"} | 200 {"hello": "world"} |
200 --{{boundary}}-- | 201 --{{boundary}}-- |
201 ''')); | 202 ''')); |
202 }); | 203 }); |
203 | 204 |
204 test('with a file with a iso-8859-1 body', () { | 205 test('with a file with a iso-8859-1 body', () { |
205 var request = new http.MultipartRequest('POST', dummyUrl); | 206 var request = new http.MultipartRequest('POST', dummyUrl); |
206 // "Ã¥" encoded as ISO-8859-1 and then read as UTF-8 results in "å". | 207 // "Ã¥" encoded as ISO-8859-1 and then read as UTF-8 results in "å". |
207 var file = new http.MultipartFile.fromString('file', 'non-ascii: "Ã¥"', | 208 var file = new http.MultipartFile.fromString('file', 'non-ascii: "Ã¥"', |
208 contentType: new ContentType('text', 'plain', charset: 'iso-8859-1')); | 209 contentType: new MediaType('text', 'plain', {'charset': 'iso-8859-1'})); |
209 request.files.add(file); | 210 request.files.add(file); |
210 | 211 |
211 expect(request, bodyMatches(''' | 212 expect(request, bodyMatches(''' |
212 --{{boundary}} | 213 --{{boundary}} |
213 content-type: text/plain; charset=iso-8859-1 | 214 content-type: text/plain; charset=iso-8859-1 |
214 content-disposition: form-data; name="file" | 215 content-disposition: form-data; name="file" |
215 | 216 |
216 non-ascii: "å" | 217 non-ascii: "å" |
217 --{{boundary}}-- | 218 --{{boundary}}-- |
218 ''')); | 219 ''')); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 content-type: application/octet-stream | 292 content-type: application/octet-stream |
292 content-disposition: form-data; name="file"; filename="test-file" | 293 content-disposition: form-data; name="file"; filename="test-file" |
293 | 294 |
294 hello | 295 hello |
295 --{{boundary}}-- | 296 --{{boundary}}-- |
296 ''')); | 297 ''')); |
297 }), completes); | 298 }), completes); |
298 }); | 299 }); |
299 }); | 300 }); |
300 } | 301 } |
OLD | NEW |