| 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 import "package:http_server/http_server.dart"; |    5 import "package:http_server/http_server.dart"; | 
|    6 import "package:mime/mime.dart"; |    6 import "package:mime/mime.dart"; | 
|    7 import "package:unittest/unittest.dart"; |    7 import "package:unittest/unittest.dart"; | 
|    8 import 'dart:async'; |    8 import 'dart:async'; | 
|    9 import 'dart:io'; |    9 import 'dart:io'; | 
|   10 import 'dart:convert'; |   10 import 'dart:convert'; | 
|   11  |   11  | 
 |   12 // Representation of a form field from a multipart/form-data form POST body. | 
|   12 class FormField { |   13 class FormField { | 
 |   14   // Name of the form field specified in Content-Disposition. | 
|   13   final String name; |   15   final String name; | 
 |   16   // Value of the form field. This is either a String or a List<int> depending | 
 |   17   // on the Content-Type. | 
|   14   final value; |   18   final value; | 
 |   19   // Content-Type of the form field. | 
|   15   final String contentType; |   20   final String contentType; | 
 |   21   // Filename if specified in Content-Disposition. | 
|   16   final String filename; |   22   final String filename; | 
|   17  |   23  | 
|   18   FormField(String this.name, |   24   FormField(String this.name, | 
|   19             this.value, |   25             this.value, | 
|   20             {String this.contentType, |   26             {String this.contentType, | 
|   21              String this.filename}); |   27              String this.filename}); | 
|   22  |   28  | 
|   23   bool operator==(other) { |   29   bool operator==(other) { | 
|   24     if (value.length != other.value.length) return false; |   30     if (value.length != other.value.length) return false; | 
|   25     for (int i = 0; i < value.length; i++) { |   31     for (int i = 0; i < value.length; i++) { | 
|   26       if (value[i] != other.value[i]) { |   32       if (value[i] != other.value[i]) { | 
|   27         return false; |   33         return false; | 
|   28       } |   34       } | 
|   29     } |   35     } | 
|   30     return name == other.name && |   36     return name == other.name && | 
|   31            contentType == other.contentType && |   37            contentType == other.contentType && | 
|   32            filename == other.filename; |   38            filename == other.filename; | 
|   33   } |   39   } | 
|   34  |   40  | 
 |   41   int get hashCode => name.hashCode; | 
 |   42  | 
|   35   String toString() { |   43   String toString() { | 
|   36     return "FormField('$name', '$value', '$contentType', '$filename')"; |   44     return "FormField('$name', '$value', '$contentType', '$filename')"; | 
|   37   } |   45   } | 
|   38 } |   46 } | 
|   39  |   47  | 
|   40 void postDataTest(List<int> message, |   48 void postDataTest(List<int> message, | 
|   41                   String contentType, |   49                   String contentType, | 
|   42                   String boundary, |   50                   String boundary, | 
|   43                   List<FormField> expectedFields) { |   51                   List<FormField> expectedFields, | 
 |   52                   {defaultEncoding: LATIN1}) { | 
|   44   HttpServer.bind("127.0.0.1", 0).then((server) { |   53   HttpServer.bind("127.0.0.1", 0).then((server) { | 
|   45     server.listen((request) { |   54     server.listen((request) { | 
|   46       String boundary = request.headers.contentType.parameters['boundary']; |   55       String boundary = request.headers.contentType.parameters['boundary']; | 
|   47       request |   56       request | 
|   48           .transform(new MimeMultipartTransformer(boundary)) |   57           .transform(new MimeMultipartTransformer(boundary)) | 
|   49           .map((part) => HttpMultipartFormData.parse( |   58           .map((part) => HttpMultipartFormData.parse( | 
|   50               part, defaultEncoding: LATIN1)) |   59               part, defaultEncoding: defaultEncoding)) | 
|   51           .map((multipart) { |   60           .map((multipart) { | 
|   52             var future; |   61             var future; | 
|   53             if (multipart.isText) { |   62             if (multipart.isText) { | 
|   54               future = multipart |   63               future = multipart.join(); | 
|   55                   .fold(new StringBuffer(), (b, s) => b..write(s)) |  | 
|   56                   .then((b) => b.toString()); |  | 
|   57             } else { |   64             } else { | 
|   58               future = multipart |   65               future = multipart.fold([], (b, s) => b..addAll(s)); | 
|   59                   .fold([], (b, s) => b..addAll(s)); |  | 
|   60             } |   66             } | 
|   61             return future |   67             return future | 
|   62                 .then((data) { |   68                 .then((data) { | 
|   63                   String contentType; |   69                   String contentType; | 
|   64                   if (multipart.contentType != null) { |   70                   if (multipart.contentType != null) { | 
|   65                     contentType = multipart.contentType.mimeType; |   71                     contentType = multipart.contentType.mimeType; | 
|   66                   } |   72                   } | 
|   67                   return new FormField( |   73                   return new FormField( | 
|   68                       multipart.contentDisposition.parameters['name'], |   74                       multipart.contentDisposition.parameters['name'], | 
|   69                       data, |   75                       data, | 
|   70                       contentType: contentType, |   76                       contentType: contentType, | 
|   71                       filename: |   77                       filename: | 
|   72                           multipart.contentDisposition.parameters['filename']); |   78                           multipart.contentDisposition.parameters['filename']); | 
|   73                 }); |   79                 }); | 
|   74           }) |   80           }) | 
|   75           .fold([], (l, f) => l..add(f)) |   81           .toList() | 
|   76           .then(Future.wait) |   82           .then(Future.wait) | 
|   77           .then((fields) { |   83           .then((fields) { | 
|   78             expect(fields, equals(expectedFields)); |   84             expect(fields, equals(expectedFields)); | 
|   79             request.response.close().then((_) => server.close()); |   85             request.response.close().then((_) => server.close()); | 
|   80           }); |   86           }); | 
|   81     }); |   87     }); | 
|   82     var client = new HttpClient(); |   88     var client = new HttpClient(); | 
|   83     client.post('127.0.0.1', server.port, '/') |   89     client.post('127.0.0.1', server.port, '/') | 
|   84         .then((request) { |   90         .then((request) { | 
|   85           request.headers.set('content-type', |   91           request.headers.set('content-type', | 
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  179  |  185  | 
|  180   postDataTest(message, |  186   postDataTest(message, | 
|  181                'multipart/form-data', |  187                'multipart/form-data', | 
|  182                '----WebKitFormBoundaryQSql8kDALM7tAkC1', |  188                '----WebKitFormBoundaryQSql8kDALM7tAkC1', | 
|  183                [new FormField('submit-name', 'Test'), |  189                [new FormField('submit-name', 'Test'), | 
|  184                 new FormField('files', |  190                 new FormField('files', | 
|  185                               data, |  191                               data, | 
|  186                               contentType: 'application/octet-stream', |  192                               contentType: 'application/octet-stream', | 
|  187                               filename: 'VERSION')]); |  193                               filename: 'VERSION')]); | 
|  188  |  194  | 
 |  195   // In Chrome, Safari and Firefox HTML entity encoding might be used for | 
 |  196   // values in form fields. The HTML entity encoding for ひらがな is | 
 |  197   // ひらがな | 
|  189   message = [ |  198   message = [ | 
|  190       45, 45, 45, 45, 45, 45, 87, 101, 98, 75, 105, 116, 70, 111, 114, 109, 66, |  199       45, 45, 45, 45, 45, 45, 87, 101, 98, 75, 105, 116, 70, 111, 114, 109, 66, | 
|  191       111, 117, 110, 100, 97, 114, 121, 118, 65, 86, 122, 117, 103, 75, 77, 116, |  200       111, 117, 110, 100, 97, 114, 121, 118, 65, 86, 122, 117, 103, 75, 77, 116, | 
|  192       90, 98, 121, 87, 111, 66, 71, 13, 10, 67, 111, 110, 116, 101, 110, 116, |  201       90, 98, 121, 87, 111, 66, 71, 13, 10, 67, 111, 110, 116, 101, 110, 116, | 
|  193       45, 68, 105, 115, 112, 111, 115, 105, 116, 105, 111, 110, 58, 32, 102, |  202       45, 68, 105, 115, 112, 111, 115, 105, 116, 105, 111, 110, 58, 32, 102, | 
|  194       111, 114, 109, 45, 100, 97, 116, 97, 59, 32, 110, 97, 109, 101, 61, 34, |  203       111, 114, 109, 45, 100, 97, 116, 97, 59, 32, 110, 97, 109, 101, 61, 34, | 
|  195       110, 97, 109, 101, 34, 13, 10, 13, 10, 38, 35, 49, 50, 52, 48, 50, 59, 38, |  204       110, 97, 109, 101, 34, 13, 10, 13, 10, 38, 35, 49, 50, 52, 48, 50, 59, 38, | 
|  196       35, 49, 50, 52, 50, 53, 59, 38, 35, 49, 50, 51, 54, 52, 59, 38, 35, 49, |  205       35, 49, 50, 52, 50, 53, 59, 38, 35, 49, 50, 51, 54, 52, 59, 38, 35, 49, | 
|  197       50, 51, 57, 52, 59, 13, 10, 45, 45, 45, 45, 45, 45, 87, 101, 98, 75, 105, |  206       50, 51, 57, 52, 59, 13, 10, 45, 45, 45, 45, 45, 45, 87, 101, 98, 75, 105, | 
|  198       116, 70, 111, 114, 109, 66, 111, 117, 110, 100, 97, 114, 121, 118, 65, 86, |  207       116, 70, 111, 114, 109, 66, 111, 117, 110, 100, 97, 114, 121, 118, 65, 86, | 
|  199       122, 117, 103, 75, 77, 116, 90, 98, 121, 87, 111, 66, 71, 45, 45, 13, 10]; |  208       122, 117, 103, 75, 77, 116, 90, 98, 121, 87, 111, 66, 71, 45, 45, 13, 10]; | 
|  200  |  209  | 
|  201   postDataTest(message, |  210   postDataTest(message, | 
|  202                'multipart/form-data', |  211                'multipart/form-data', | 
|  203                '----WebKitFormBoundaryvAVzugKMtZbyWoBG', |  212                '----WebKitFormBoundaryvAVzugKMtZbyWoBG', | 
|  204                [new FormField('name', 'ひらがな')]); |  213                [new FormField('name', 'ひらがな')], | 
 |  214                defaultEncoding: UTF8); | 
 |  215  | 
 |  216   // The UTF-8 encoding of ひらがな is | 
 |  217   // [227, 129, 178, 227, 130, 137, 227, 129, 140, 227, 129, 170]. | 
 |  218   message = [ | 
 |  219       45, 45, 45, 45, 45, 45, 87, 101, 98, 75, 105, 116, 70, 111, 114, 109, 66, | 
 |  220       111, 117, 110, 100, 97, 114, 121, 71, 88, 116, 66, 114, 99, 106, 120, 104, | 
 |  221       101, 75, 101, 78, 54, 105, 48, 13, 10, 67, 111, 110, 116, 101, 110, 116, | 
 |  222       45, 68, 105, 115, 112, 111, 115, 105, 116, 105, 111, 110, 58, 32, 102, | 
 |  223       111, 114, 109, 45, 100, 97, 116, 97, 59, 32, 110, 97, 109, 101, 61, 34, | 
 |  224       116, 101, 115, 116, 34, 13, 10, 13, 10, 227, 129, 178, 227, 130, 137, 227, | 
 |  225       129, 140, 227, 129, 170, 13, 10, 45, 45, 45, 45, 45, 45, 87, 101, 98, 75, | 
 |  226       105, 116, 70, 111, 114, 109, 66, 111, 117, 110, 100, 97, 114, 121, 71, 88, | 
 |  227       116, 66, 114, 99, 106, 120, 104, 101, 75, 101, 78, 54, 105, 48, 45, 45, | 
 |  228       13, 10]; | 
 |  229  | 
 |  230   postDataTest(message, | 
 |  231                'multipart/form-data', | 
 |  232                '----WebKitFormBoundaryGXtBrcjxheKeN6i0', | 
 |  233                [new FormField('test', 'ひらがな')], | 
 |  234                defaultEncoding: UTF8); | 
|  205  |  235  | 
|  206   message = [ |  236   message = [ | 
|  207       45, 45, 45, 45, 45, 45, 87, 101, 98, 75, 105, 116, 70, 111, 114, 109, 66, |  237       45, 45, 45, 45, 45, 45, 87, 101, 98, 75, 105, 116, 70, 111, 114, 109, 66, | 
|  208       111, 117, 110, 100, 97, 114, 121, 102, 101, 48, 69, 122, 86, 49, 97, 78, |  238       111, 117, 110, 100, 97, 114, 121, 102, 101, 48, 69, 122, 86, 49, 97, 78, | 
|  209       121, 115, 68, 49, 98, 80, 104, 13, 10, 67, 111, 110, 116, 101, 110, 116, |  239       121, 115, 68, 49, 98, 80, 104, 13, 10, 67, 111, 110, 116, 101, 110, 116, | 
|  210       45, 68, 105, 115, 112, 111, 115, 105, 116, 105, 111, 110, 58, 32, 102, |  240       45, 68, 105, 115, 112, 111, 115, 105, 116, 105, 111, 110, 58, 32, 102, | 
|  211       111, 114, 109, 45, 100, 97, 116, 97, 59, 32, 110, 97, 109, 101, 61, 34, |  241       111, 114, 109, 45, 100, 97, 116, 97, 59, 32, 110, 97, 109, 101, 61, 34, | 
|  212       110, 97, 109, 101, 34, 13, 10, 13, 10, 248, 118, 13, 10, 45, 45, 45, 45, |  242       110, 97, 109, 101, 34, 13, 10, 13, 10, 248, 118, 13, 10, 45, 45, 45, 45, | 
|  213       45, 45, 87, 101, 98, 75, 105, 116, 70, 111, 114, 109, 66, 111, 117, 110, |  243       45, 45, 87, 101, 98, 75, 105, 116, 70, 111, 114, 109, 66, 111, 117, 110, | 
|  214       100, 97, 114, 121, 102, 101, 48, 69, 122, 86, 49, 97, 78, 121, 115, 68, |  244       100, 97, 114, 121, 102, 101, 48, 69, 122, 86, 49, 97, 78, 121, 115, 68, | 
|  215       49, 98, 80, 104, 45, 45, 13, 10]; |  245       49, 98, 80, 104, 45, 45, 13, 10]; | 
|  216  |  246  | 
|  217   postDataTest(message, |  247   postDataTest(message, | 
|  218                'multipart/form-data', |  248                'multipart/form-data', | 
|  219                '----WebKitFormBoundaryfe0EzV1aNysD1bPh', |  249                '----WebKitFormBoundaryfe0EzV1aNysD1bPh', | 
|  220                [new FormField('name', 'øv')]); |  250                [new FormField('name', 'øv')]); | 
|  221 } |  251 } | 
|  222  |  252  | 
|  223  |  253  | 
|  224 void main() { |  254 void main() { | 
|  225   testEmptyPostData(); |  255   testEmptyPostData(); | 
|  226   testPostData(); |  256   testPostData(); | 
|  227 } |  257 } | 
| OLD | NEW |