Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(708)

Side by Side Diff: pkg/http/lib/src/multipart_request.dart

Issue 19866007: pkg/http tweaks (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: a few more dart:io removals Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/http/lib/src/client.dart ('k') | pkg/http/lib/src/streamed_request.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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_request; 5 library multipart_request;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:io';
9 import 'dart:math'; 8 import 'dart:math';
10 import 'dart:utf'; 9 import 'dart:utf';
11 10
12 import 'base_request.dart'; 11 import 'base_request.dart';
13 import 'byte_stream.dart'; 12 import 'byte_stream.dart';
14 import 'multipart_file.dart'; 13 import 'multipart_file.dart';
15 import 'utils.dart'; 14 import 'utils.dart';
16 15
17 /// A `multipart/form-data` request. Such a request has both string [fields], 16 /// A `multipart/form-data` request. Such a request has both string [fields],
18 /// which function as normal form fields, and (potentially streamed) binary 17 /// which function as normal form fields, and (potentially streamed) binary
(...skipping 10 matching lines...) Expand all
29 /// 'package', 28 /// 'package',
30 /// new File('build/package.tar.gz'), 29 /// new File('build/package.tar.gz'),
31 /// contentType: new ContentType('application', 'x-tar')); 30 /// contentType: new ContentType('application', 'x-tar'));
32 /// request.send().then((response) { 31 /// request.send().then((response) {
33 /// if (response.statusCode == 200) print("Uploaded!"); 32 /// if (response.statusCode == 200) print("Uploaded!");
34 /// }); 33 /// });
35 class MultipartRequest extends BaseRequest { 34 class MultipartRequest extends BaseRequest {
36 /// The total length of the multipart boundaries used when building the 35 /// The total length of the multipart boundaries used when building the
37 /// request body. According to http://tools.ietf.org/html/rfc1341.html, this 36 /// request body. According to http://tools.ietf.org/html/rfc1341.html, this
38 /// can't be longer than 70. 37 /// can't be longer than 70.
39 static final int _BOUNDARY_LENGTH = 70; 38 static const int _BOUNDARY_LENGTH = 70;
40 39
41 static final Random _random = new Random(); 40 static final Random _random = new Random();
42 41
43 /// The form fields to send for this request. 42 /// The form fields to send for this request.
44 final Map<String, String> fields; 43 final Map<String, String> fields;
45 44
46 /// The private version of [files]. 45 /// The private version of [files].
47 final List<MultipartFile> _files; 46 final List<MultipartFile> _files;
48 47
49 /// Creates a new [MultipartRequest]. 48 /// Creates a new [MultipartRequest].
(...skipping 18 matching lines...) Expand all
68 67
69 for (var file in _files) { 68 for (var file in _files) {
70 length += "--".length + _BOUNDARY_LENGTH + "\r\n".length + 69 length += "--".length + _BOUNDARY_LENGTH + "\r\n".length +
71 _headerForFile(file).length + 70 _headerForFile(file).length +
72 file.length + "\r\n".length; 71 file.length + "\r\n".length;
73 } 72 }
74 73
75 return length + "--".length + _BOUNDARY_LENGTH + "--\r\n".length; 74 return length + "--".length + _BOUNDARY_LENGTH + "--\r\n".length;
76 } 75 }
77 76
78 set contentLength(int value) {
79 throw new UnsupportedError("Cannot set the contentLength property of "
80 "multipart requests.");
81 }
nweiz 2013/07/23 20:18:49 Why is this being removed? It shouldn't be possibl
kevmoo-old 2013/07/23 21:08:56 Didn't read the type hierarchy correctly. Oops.
82
83 /// Freezes all mutable fields and returns a single-subscription [ByteStream] 77 /// Freezes all mutable fields and returns a single-subscription [ByteStream]
84 /// that will emit the request body. 78 /// that will emit the request body.
85 ByteStream finalize() { 79 ByteStream finalize() {
86 // TODO(nweiz): freeze fields and files 80 // TODO(nweiz): freeze fields and files
87 var boundary = _boundaryString(_BOUNDARY_LENGTH); 81 var boundary = _boundaryString(_BOUNDARY_LENGTH);
88 headers['content-type'] = 'multipart/form-data; boundary="$boundary"'; 82 headers['content-type'] = 'multipart/form-data; boundary="$boundary"';
89 headers['content-transfer-encoding'] = 'binary'; 83 headers['content-transfer-encoding'] = 'binary';
90 super.finalize(); 84 super.finalize();
91 85
92 var controller = new StreamController<List<int>>(sync: true); 86 var controller = new StreamController<List<int>>(sync: true);
(...skipping 23 matching lines...) Expand all
116 // the stream. See issue 3657. 110 // the stream. See issue 3657.
117 writeAscii('--$boundary--\r\n'); 111 writeAscii('--$boundary--\r\n');
118 controller.close(); 112 controller.close();
119 }); 113 });
120 114
121 return new ByteStream(controller.stream); 115 return new ByteStream(controller.stream);
122 } 116 }
123 117
124 /// All character codes that are valid in multipart boundaries. From 118 /// All character codes that are valid in multipart boundaries. From
125 /// http://tools.ietf.org/html/rfc2046#section-5.1.1. 119 /// http://tools.ietf.org/html/rfc2046#section-5.1.1.
126 static final List<int> _BOUNDARY_CHARACTERS = const <int>[ 120 static const List<int> _BOUNDARY_CHARACTERS = const <int>[
127 39, 40, 41, 43, 95, 44, 45, 46, 47, 58, 61, 63, 48, 49, 50, 51, 52, 53, 54, 121 39, 40, 41, 43, 95, 44, 45, 46, 47, 58, 61, 63, 48, 49, 50, 51, 52, 53, 54,
128 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 122 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
129 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 123 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103,
130 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 124 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
131 119, 120, 121, 122 125 119, 120, 121, 122
132 ]; 126 ];
133 127
134 /// Returns the header string for a field. The return value is guaranteed to 128 /// Returns the header string for a field. The return value is guaranteed to
135 /// contain only ASCII characters. 129 /// contain only ASCII characters.
136 String _headerForField(String name, String value) { 130 static String _headerForField(String name, String value) {
nweiz 2013/07/23 20:18:49 I'm not a fan of making methods static just becaus
kevmoo-old 2013/07/23 21:08:56 I think it correctly communicates it *could* be ac
nweiz 2013/07/23 21:27:34 It's an implementation detail that it doesn't acce
kevmoo-old 2013/07/23 21:36:37 I'm cool w/ philosophical differences here. Not a
137 // http://tools.ietf.org/html/rfc2388 mandates some complex encodings for 131 // http://tools.ietf.org/html/rfc2388 mandates some complex encodings for
138 // field names and file names, but in practice user agents seem to just 132 // field names and file names, but in practice user agents seem to just
139 // URL-encode them so we do the same. 133 // URL-encode them so we do the same.
140 var header = 134 var header =
141 'content-disposition: form-data; name="${Uri.encodeFull(name)}"'; 135 'content-disposition: form-data; name="${Uri.encodeFull(name)}"';
142 if (!isPlainAscii(value)) { 136 if (!isPlainAscii(value)) {
143 header = '$header\r\ncontent-type: text/plain; charset=utf-8'; 137 header = '$header\r\ncontent-type: text/plain; charset=utf-8';
144 } 138 }
145 return '$header\r\n\r\n'; 139 return '$header\r\n\r\n';
146 } 140 }
147 141
148 /// Returns the header string for a file. The return value is guaranteed to 142 /// Returns the header string for a file. The return value is guaranteed to
149 /// contain only ASCII characters. 143 /// contain only ASCII characters.
150 String _headerForFile(MultipartFile file) { 144 static String _headerForFile(MultipartFile file) {
151 var header = 'content-type: ${file.contentType}\r\n' 145 var header = 'content-type: ${file.contentType}\r\n'
152 'content-disposition: form-data; name="${Uri.encodeFull(file.field)}"'; 146 'content-disposition: form-data; name="${Uri.encodeFull(file.field)}"';
153 147
154 if (file.filename != null) { 148 if (file.filename != null) {
155 header = '$header; filename="${Uri.encodeFull(file.filename)}"'; 149 header = '$header; filename="${Uri.encodeFull(file.filename)}"';
156 } 150 }
157 return '$header\r\n\r\n'; 151 return '$header\r\n\r\n';
158 } 152 }
159 153
160 /// Returns a randomly-generated multipart boundary string of the given 154 /// Returns a randomly-generated multipart boundary string of the given
161 /// [length]. 155 /// [length].
162 String _boundaryString(int length) { 156 static String _boundaryString(int length) {
163 var prefix = "dart-http-boundary-"; 157 const prefix = "dart-http-boundary-";
nweiz 2013/07/23 20:18:49 Also not a fan of const local variables, for rough
kevmoo-old 2013/07/23 21:08:56 Fair.
164 var list = new List<int>(length - prefix.length); 158 var list = new List<int>(length - prefix.length);
165 for (var i = 0; i < list.length; i++) { 159 for (var i = 0; i < list.length; i++) {
166 list[i] = _BOUNDARY_CHARACTERS[ 160 list[i] = _BOUNDARY_CHARACTERS[
167 _random.nextInt(_BOUNDARY_CHARACTERS.length)]; 161 _random.nextInt(_BOUNDARY_CHARACTERS.length)];
168 } 162 }
169 return "$prefix${new String.fromCharCodes(list)}"; 163 return "$prefix${new String.fromCharCodes(list)}";
170 } 164 }
171 } 165 }
OLDNEW
« no previous file with comments | « pkg/http/lib/src/client.dart ('k') | pkg/http/lib/src/streamed_request.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698