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 part of http_server; | 5 part of http_server; |
6 | 6 |
7 class _HttpBodyHandlerTransformer | 7 class _HttpBodyHandlerTransformer |
8 extends StreamEventTransformer<HttpRequest, HttpRequestBody> { | 8 extends StreamEventTransformer<HttpRequest, HttpRequestBody> { |
9 final Encoding _defaultEncoding; | 9 final Encoding _defaultEncoding; |
10 _HttpBodyHandlerTransformer(this._defaultEncoding); | 10 _HttpBodyHandlerTransformer(this._defaultEncoding); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 return stream | 46 return stream |
47 .fold(new BytesBuilder(), (builder, data) => builder..add(data)) | 47 .fold(new BytesBuilder(), (builder, data) => builder..add(data)) |
48 .then((builder) => new _HttpBody(contentType, | 48 .then((builder) => new _HttpBody(contentType, |
49 "binary", | 49 "binary", |
50 builder.takeBytes())); | 50 builder.takeBytes())); |
51 } | 51 } |
52 | 52 |
53 Future<HttpBody> asText(Encoding defaultEncoding) { | 53 Future<HttpBody> asText(Encoding defaultEncoding) { |
54 var encoding; | 54 var encoding; |
55 var charset = contentType.charset; | 55 var charset = contentType.charset; |
56 if (charset != null) encoding = Encoding.fromName(charset); | 56 if (charset != null) encoding = Encoding.getByName(charset); |
57 if (encoding == null) encoding = defaultEncoding; | 57 if (encoding == null) encoding = defaultEncoding; |
58 return stream | 58 return stream |
59 .transform(new StringDecoder(encoding)) | 59 .transform(encoding.decoder) |
60 .fold(new StringBuffer(), (buffer, data) => buffer..write(data)) | 60 .fold(new StringBuffer(), (buffer, data) => buffer..write(data)) |
61 .then((buffer) => new _HttpBody(contentType, | 61 .then((buffer) => new _HttpBody(contentType, |
62 "text", | 62 "text", |
63 buffer.toString())); | 63 buffer.toString())); |
64 } | 64 } |
65 | 65 |
66 Future<HttpBody> asFormData() { | 66 Future<HttpBody> asFormData() { |
67 return stream | 67 return stream |
68 .transform(new MimeMultipartTransformer( | 68 .transform(new MimeMultipartTransformer( |
69 contentType.parameters['boundary'])) | 69 contentType.parameters['boundary'])) |
(...skipping 30 matching lines...) Expand all Loading... |
100 return new _HttpBody(contentType, 'form', map); | 100 return new _HttpBody(contentType, 'form', map); |
101 }); | 101 }); |
102 } | 102 } |
103 | 103 |
104 if (contentType == null) { | 104 if (contentType == null) { |
105 return asBinary(); | 105 return asBinary(); |
106 } | 106 } |
107 | 107 |
108 switch (contentType.primaryType) { | 108 switch (contentType.primaryType) { |
109 case "text": | 109 case "text": |
110 return asText(Encoding.ASCII); | 110 return asText(ASCII); |
111 | 111 |
112 case "application": | 112 case "application": |
113 switch (contentType.subType) { | 113 switch (contentType.subType) { |
114 case "json": | 114 case "json": |
115 return asText(Encoding.UTF_8) | 115 return asText(UTF8) |
116 .then((body) => new _HttpBody(contentType, | 116 .then((body) => new _HttpBody(contentType, |
117 "json", | 117 "json", |
118 JSON.parse(body.body))); | 118 JSON.parse(body.body))); |
119 | 119 |
120 case "x-www-form-urlencoded": | 120 case "x-www-form-urlencoded": |
121 return asText(Encoding.ASCII) | 121 return asText(ASCII) |
122 .then((body) { | 122 .then((body) { |
123 var map = Uri.splitQueryString(body.body, | 123 var map = Uri.splitQueryString(body.body, |
124 decode: (s) => _decodeString(s, defaultEncoding)); | 124 decode: (s) => defaultEncoding.decode(s)); |
125 var result = {}; | 125 var result = {}; |
126 for (var key in map.keys) { | 126 for (var key in map.keys) { |
127 result[key] = map[key]; | 127 result[key] = map[key]; |
128 } | 128 } |
129 return new _HttpBody(contentType, "form", result); | 129 return new _HttpBody(contentType, "form", result); |
130 }); | 130 }); |
131 | 131 |
132 default: | 132 default: |
133 break; | 133 break; |
134 } | 134 } |
135 break; | 135 break; |
136 | 136 |
137 case "multipart": | 137 case "multipart": |
138 switch (contentType.subType) { | 138 switch (contentType.subType) { |
139 case "form-data": | 139 case "form-data": |
140 return asFormData(); | 140 return asFormData(); |
141 | 141 |
142 default: | 142 default: |
143 break; | 143 break; |
144 } | 144 } |
145 break; | 145 break; |
146 | 146 |
147 default: | 147 default: |
148 break; | 148 break; |
149 } | 149 } |
150 | 150 |
151 return asBinary(); | 151 return asBinary(); |
152 } | 152 } |
153 | |
154 // Utility function to synchronously decode a list of bytes. | |
155 static String _decodeString(List<int> bytes, | |
156 [Encoding encoding = Encoding.UTF_8]) { | |
157 if (bytes.length == 0) return ""; | |
158 var string; | |
159 var error; | |
160 var controller = new StreamController(sync: true); | |
161 controller.stream | |
162 .transform(new StringDecoder(encoding)) | |
163 .listen((data) => string = data, | |
164 onError: (e) => error = e); | |
165 controller.add(bytes); | |
166 controller.close(); | |
167 if (error != null) throw error; | |
168 assert(string != null); | |
169 return string; | |
170 } | |
171 } | 153 } |
172 | 154 |
173 class _HttpBodyFileUpload implements HttpBodyFileUpload { | 155 class _HttpBodyFileUpload implements HttpBodyFileUpload { |
174 final ContentType contentType; | 156 final ContentType contentType; |
175 final String filename; | 157 final String filename; |
176 final dynamic content; | 158 final dynamic content; |
177 _HttpBodyFileUpload(this.contentType, this.filename, this.content); | 159 _HttpBodyFileUpload(this.contentType, this.filename, this.content); |
178 } | 160 } |
179 | 161 |
180 class _HttpBody implements HttpBody { | 162 class _HttpBody implements HttpBody { |
(...skipping 27 matching lines...) Expand all Loading... |
208 _HttpClientResponseBody(HttpClientResponse response, HttpBody body) | 190 _HttpClientResponseBody(HttpClientResponse response, HttpBody body) |
209 : super(body.contentType, body.type, body.body), | 191 : super(body.contentType, body.type, body.body), |
210 this.response = response; | 192 this.response = response; |
211 | 193 |
212 int get statusCode => response.statusCode; | 194 int get statusCode => response.statusCode; |
213 | 195 |
214 String get reasonPhrase => response.reasonPhrase; | 196 String get reasonPhrase => response.reasonPhrase; |
215 | 197 |
216 HttpHeaders get headers => response.headers; | 198 HttpHeaders get headers => response.headers; |
217 } | 199 } |
OLD | NEW |