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

Unified Diff: pkg/http_server/lib/src/http_body_impl.dart

Issue 18438005: Move MimeMultipartTransformer and HttpBodyHandler to mime and http_server packages. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 6 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 side-by-side diff with in-line comments
Download patch
Index: pkg/http_server/lib/src/http_body_impl.dart
diff --git a/sdk/lib/io/http_body_impl.dart b/pkg/http_server/lib/src/http_body_impl.dart
similarity index 50%
rename from sdk/lib/io/http_body_impl.dart
rename to pkg/http_server/lib/src/http_body_impl.dart
index 900dff51e9304d8349993e36a0972c2b38ad8584..1ccf49291d00642006515bd1194e539b1b820da9 100644
--- a/sdk/lib/io/http_body_impl.dart
+++ b/pkg/http_server/lib/src/http_body_impl.dart
@@ -2,7 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-part of dart.io;
+part of http_server;
class _HttpBodyHandlerTransformer
extends StreamEventTransformer<HttpRequest, HttpRequestBody> {
@@ -120,7 +120,7 @@ class _HttpBodyHandler {
case "x-www-form-urlencoded":
return asText(Encoding.ASCII)
.then((body) {
- var map = _HttpUtils.splitQueryString(
+ var map = _splitQueryString(
body.body, encoding: defaultEncoding);
var result = {};
for (var key in map.keys) {
@@ -197,3 +197,230 @@ class _HttpClientResponseBody
HttpHeaders get headers => response.headers;
}
+
+
+class _CharCode {
+ static const int AMPERSAND = 38;
+ static const int SEMI_COLON = 59;
+ static const int EQUAL = 61;
+}
+
+
+// TODO(ajohnsen): Provide in dart:io?
Bill Hesse 2013/07/03 11:30:27 Do you now mean "Provide in pkg/http_server?" Do
Anders Johnsen 2013/07/12 10:45:57 Removed.
+Map<String, String> _splitQueryString(String queryString,
+ {Encoding encoding: Encoding.UTF_8}) {
+ Map<String, String> result = new Map<String, String>();
+ int currentPosition = 0;
+ int length = queryString.length;
+
+ while (currentPosition < length) {
+
+ // Find the first equals character between current position and
+ // the provided end.
Bill Hesse 2013/07/03 11:30:27 I don't think you need this function. You can, in
Anders Johnsen 2013/07/12 10:45:57 This is gone.
+ int indexOfEquals(int end) {
+ int index = currentPosition;
+ while (index < end) {
+ if (queryString.codeUnitAt(index) == _CharCode.EQUAL) return index;
+ index++;
+ }
+ return -1;
+ }
+
+ // Find the next separator (either & or ;), see
+ // http://www.w3.org/TR/REC-html40/appendix/notes.html#ampersands-in-uris
+ // relating the ; separator. If no separator is found returns
+ // the length of the query string.
+ int indexOfSeparator() {
+ int end = length;
+ int index = currentPosition;
+ while (index < end) {
+ int codeUnit = queryString.codeUnitAt(index);
+ if (codeUnit == _CharCode.AMPERSAND ||
+ codeUnit == _CharCode.SEMI_COLON) {
+ return index;
+ }
+ index++;
+ }
+ return end;
+ }
+
+ int seppos = indexOfSeparator();
+ int equalspos = indexOfEquals(seppos);
+ String name;
+ String value;
+ if (equalspos == -1) {
+ name = queryString.substring(currentPosition, seppos);
+ value = '';
+ } else {
+ name = queryString.substring(currentPosition, equalspos);
+ value = queryString.substring(equalspos + 1, seppos);
+ }
+ currentPosition = seppos + 1; // This also works when seppos == length.
+ if (name == '') continue;
+ result[_decodeUrlEncodedString(name, encoding: encoding)] =
+ _decodeUrlEncodedString(value, encoding: encoding);
+ }
+ return result;
+}
+
+
+// TODO(ajohnsen): Provide in dart:io?
+String _decodeUrlEncodedString(String urlEncoded,
+ {Encoding encoding: Encoding.UTF_8}) {
+ // First check the string for any encoding.
+ int index = 0;
+ bool encoded = false;
+ while (!encoded && index < urlEncoded.length) {
Bill Hesse 2013/07/03 11:30:27 .indexOf(RegExp('[%+]'))?
Anders Johnsen 2013/07/12 10:45:57 This is gone.
+ encoded = urlEncoded[index] == "+" || urlEncoded[index] == "%";
+ index++;
+ }
+ if (!encoded) return urlEncoded;
+ index--;
+
+ // Start decoding from the first encoded character.
+ List<int> bytes = new List<int>();
+ for (int i = 0; i < index; i++) bytes.add(urlEncoded.codeUnitAt(i));
+ for (int i = index; i < urlEncoded.length; i++) {
+ if (urlEncoded[i] == "+") {
+ bytes.add(32);
+ } else if (urlEncoded[i] == "%") {
+ if (urlEncoded.length - i < 2) {
+ throw new HttpException("Invalid URL encoding");
+ }
+ int byte = 0;
+ for (int j = 0; j < 2; j++) {
+ var charCode = urlEncoded.codeUnitAt(i + j + 1);
+ if (0x30 <= charCode && charCode <= 0x39) {
+ byte = byte * 16 + charCode - 0x30;
+ } else {
+ // Check ranges A-F (0x41-0x46) and a-f (0x61-0x66).
+ charCode |= 0x20;
+ if (0x61 <= charCode && charCode <= 0x66) {
+ byte = byte * 16 + charCode - 0x57;
+ } else {
+ throw new ArgumentError("Invalid URL encoding");
+ }
+ }
+ }
+ bytes.add(byte);
+ i += 2;
+ } else {
+ bytes.add(urlEncoded.codeUnitAt(i));
+ }
+ }
+ return _decodeString(bytes, encoding);
+}
+
+// Utility function to synchronously decode a list of bytes.
+// TODO(ajohnsen): Provide in dart:?.
+String _decodeString(List<int> bytes, [Encoding encoding = Encoding.UTF_8]) {
+ if (bytes.length == 0) return "";
+ var string;
+ var error;
+ var controller = new StreamController(sync: true);
+ controller.stream
+ .transform(new StringDecoder(encoding))
+ .listen((data) => string = data,
+ onError: (e) => error = e);
+ controller.add(bytes);
+ controller.close();
+ if (error != null) throw error;
+ assert(string != null);
+ return string;
+}
+
+/**
+ * Utility class that can fast concatenate [List<int>]s of bytes. Use
+ * [readBytes] to get the final buffer.
+ */
+// TODO(ajohnsen): Provide in dart:io?
+class _BufferList {
+ const int _INIT_SIZE = 1 * 1024;
+
+ _BufferList() {
+ clear();
+ }
+
+ int pow2roundup(int x) {
+ --x;
+ x |= x >> 1;
+ x |= x >> 2;
+ x |= x >> 4;
+ x |= x >> 8;
+ x |= x >> 16;
+ return x + 1;
+ }
+
+ /**
+ * Adds a new buffer to the list.
+ */
+ void add(List<int> buffer) {
Bill Hesse 2013/07/03 11:30:27 buffer and _buffer in the same function is confusi
Anders Johnsen 2013/07/12 10:45:57 Also gone.
+ int bufferLength = buffer.length;
+ int required = _length + bufferLength;
+ if (_buffer == null) {
+ int size = pow2roundup(required);
+ if (size < _INIT_SIZE) size = _INIT_SIZE;
+ _buffer = new Uint8List(size);
+ } else if (_buffer.length < required) {
+ // This will give is a list in the range of 2-4 times larger than
+ // required.
+ int size = pow2roundup(required) * 2;
+ Uint8List newBuffer = new Uint8List(size);
+ newBuffer.setRange(0, _buffer.length, _buffer);
+ _buffer = newBuffer;
+ }
+ assert(_buffer.length >= required);
+ if (buffer is Uint8List) {
+ _buffer.setRange(_length, required, buffer);
+ } else {
+ for (int i = 0; i < bufferLength; i++) {
Bill Hesse 2013/07/03 11:30:27 Why aren't we using setRange for both cases?
Anders Johnsen 2013/07/12 10:45:57 We are now.
+ _buffer[_length + i] = buffer[i];
+ }
+ }
+ _length = required;
+ }
+
+ /**
+ * Same as [add].
+ */
+ void write(List<int> buffer) {
+ add(buffer);
+ }
+
+ /**
+ * Read all the bytes from the buffer list. If it's empty, an empty list
+ * is returned. A call to [readBytes] will clear the buffer.
+ */
+ List<int> readBytes() {
+ if (_buffer == null) return new Uint8List(0);
+ var buffer = new Uint8List.view(_buffer.buffer, 0, _length);
+ clear();
+ return buffer;
+ }
+
+ /**
+ * Returns the total number of bytes in the buffer.
+ */
+ int get length => _length;
+
+ /**
+ * Returns whether the buffer list is empty.
+ */
+ bool get isEmpty => _length == 0;
+
+ /**
+ * Returns whether the buffer list is not empty.
+ */
+ bool get isNotEmpty => !isEmpty;
+
+ /**
+ * Clears the content of the buffer list.
+ */
+ void clear() {
+ _length = 0;
+ _buffer = null;
+ }
+
+ int _length; // Total number of bytes in the buffer.
+ Uint8List _buffer; // Internal buffer.
+}

Powered by Google App Engine
This is Rietveld 408576698