Chromium Code Reviews| Index: sdk/lib/io/http_body_impl.dart |
| diff --git a/sdk/lib/io/http_body_impl.dart b/sdk/lib/io/http_body_impl.dart |
| index 095b74e7048799b86c14d6e39d8fe32d35018a35..4410a0e29b284701255b97d194b3d1f96b95ce40 100644 |
| --- a/sdk/lib/io/http_body_impl.dart |
| +++ b/sdk/lib/io/http_body_impl.dart |
| @@ -33,59 +33,119 @@ class _HttpBodyHandler { |
| static Future<HttpBody> process(Stream<List<int>> stream, |
| HttpHeaders headers) { |
| - return stream.fold( |
| - new _BufferList(), |
| - (buffer, data) { |
| - // TODO(ajohnsen): Add limit for POST data. |
| - buffer.add(data); |
| - return buffer; |
| - }) |
| - .then((list) { |
| - dynamic content = list.readBytes(); |
| - String type = "binary"; |
| - ContentType contentType = headers.contentType; |
| - if (contentType == null) { |
| - return new _HttpBody(null, type, content); |
| - } |
| - String asText(Encoding defaultEncoding) { |
| - var encoding; |
| - var charset = contentType.charset; |
| - if (charset != null) encoding = Encoding.fromName(charset); |
| - if (encoding == null) encoding = defaultEncoding; |
| - return _decodeString(content, encoding); |
| - } |
| - switch (contentType.primaryType) { |
| - case "text": |
| - type = "text"; |
| - content = asText(Encoding.ASCII); |
| - break; |
| - |
| - case "application": |
| - switch (contentType.subType) { |
| - case "json": |
| - content = JSON.parse(asText(Encoding.UTF_8)); |
| - type = "json"; |
| - break; |
| - |
| - default: |
| - break; |
| + ContentType contentType = headers.contentType; |
| + |
| + Future<HttpBody> asBinary() { |
| + return stream |
| + .fold(new _BufferList(), (buffer, data) => buffer..add(data)) |
| + .then((buffer) => new _HttpBody(contentType, |
| + "binary", |
| + buffer.readBytes())); |
| + } |
| + |
| + Future<HttpBody> asText(Encoding defaultEncoding) { |
| + var encoding; |
| + var charset = contentType.charset; |
| + if (charset != null) encoding = Encoding.fromName(charset); |
| + if (encoding == null) encoding = defaultEncoding; |
| + return stream |
| + .transform(new StringDecoder(encoding)) |
| + .fold(new StringBuffer(), (buffer, data) => buffer..write(data)) |
| + .then((buffer) => new _HttpBody(contentType, |
| + "text", |
| + buffer.toString())); |
| + } |
| + |
| + Future<HttpBody> asFormData() { |
| + return stream |
| + .transform(new MimeMultipartTransformer( |
| + contentType.parameters['boundary'])) |
| + .map((HttpMultipartFormData.parse)) |
| + .map((multipart) { |
| + var future; |
| + if (multipart.isText) { |
| + future = multipart |
| + .fold(new StringBuffer(), (b, s) => b..write(s)) |
| + .then((b) => b.toString()); |
| + } else { |
| + future = multipart |
| + .fold(new _BufferList(), (b, d) => b..add(d)) |
| + .then((b) => b.readBytes()); |
| + } |
| + return future.then((data) { |
| + var filename = |
| + multipart.contentDisposition.parameters['filename']; |
| + if (filename != null) { |
| + data = new _HttpBodyFileUpload(multipart.contentType, |
| + filename, |
| + data); |
| } |
| - break; |
| - |
| - default: |
| - break; |
| - } |
| - return new _HttpBody(contentType.mimeType, type, content); |
| - }); |
| + return [multipart.contentDisposition.parameters['name'], data]; |
| + }); |
| + }) |
| + .fold([], (l, f) => l..add(f)) |
|
Søren Gjesse
2013/05/07 09:31:31
Does this ensure that if there are more than one f
Anders Johnsen
2013/06/11 12:23:01
Yep, it preserves the of the fields.
|
| + .then(Future.wait) |
| + .then((parts) { |
| + Map<String, dynamic> map = new Map<String, dynamic>(); |
| + for (var part in parts) { |
| + map[part[0]] = part[1]; // Override existing entries. |
| + } |
| + return new _HttpBody(contentType, 'form', map); |
| + }); |
| + } |
| + |
| + if (contentType == null) { |
| + return asBinary(); |
| + } |
| + |
| + switch (contentType.primaryType) { |
| + case "text": |
| + return asText(Encoding.ASCII); |
| + |
| + case "application": |
| + switch (contentType.subType) { |
| + case "json": |
| + return asText(Encoding.UTF_8) |
| + .then((body) => new _HttpBody(contentType, |
| + "json", |
| + JSON.parse(body.body))); |
| + |
| + default: |
| + break; |
| + } |
| + break; |
| + |
| + case "multipart": |
| + switch (contentType.subType) { |
| + case "form-data": |
| + return asFormData(); |
| + |
| + default: |
| + break; |
| + } |
| + break; |
| + |
| + default: |
| + break; |
| + } |
| + |
| + return asBinary(); |
| } |
| } |
| +class _HttpBodyFileUpload implements HttpBodyFileUpload { |
| + final ContentType contentType; |
| + final String filename; |
| + final dynamic content; |
| + _HttpBodyFileUpload(this.contentType, this.filename, this.content); |
| +} |
| + |
| class _HttpBody implements HttpBody { |
| - final String mimeType; |
| + final ContentType contentType; |
| final String type; |
| final dynamic body; |
| - _HttpBody(String this.mimeType, |
| + _HttpBody(ContentType this.contentType, |
| String this.type, |
| dynamic this.body); |
| } |
| @@ -97,7 +157,7 @@ class _HttpRequestBody extends _HttpBody implements HttpRequestBody { |
| final HttpResponse response; |
| _HttpRequestBody(HttpRequest request, HttpBody body) |
| - : super(body.mimeType, body.type, body.body), |
| + : super(body.contentType, body.type, body.body), |
| method = request.method, |
| uri = request.uri, |
| headers = request.headers, |
| @@ -109,7 +169,7 @@ class _HttpClientResponseBody |
| final HttpClientResponse response; |
| _HttpClientResponseBody(HttpClientResponse response, HttpBody body) |
| - : super(body.mimeType, body.type, body.body), |
| + : super(body.contentType, body.type, body.body), |
| this.response = response; |
| int get statusCode => response.statusCode; |