Index: sdk/lib/io/http_impl.dart |
diff --git a/sdk/lib/io/http_impl.dart b/sdk/lib/io/http_impl.dart |
index b4d83af6f213afe73fe422b2b1882bff70e862a3..0ac2c7d5f80b83c0ce9a01e6c0045364e153d5a0 100644 |
--- a/sdk/lib/io/http_impl.dart |
+++ b/sdk/lib/io/http_impl.dart |
@@ -332,7 +332,7 @@ abstract class _HttpOutboundMessage<T> implements IOSink { |
_HttpOutboundMessage(String protocolVersion, _HttpOutgoing outgoing) |
: _outgoing = outgoing, |
- _ioSink = new IOSink(outgoing), |
+ _ioSink = new IOSink(outgoing, Encoding.ASCII), |
headers = new _HttpHeaders(protocolVersion); |
int get contentLength => headers.contentLength; |
@@ -345,28 +345,75 @@ abstract class _HttpOutboundMessage<T> implements IOSink { |
headers.persistentConnection = p; |
} |
- Future<T> consume(Stream<List<int>> stream) { |
+ Encoding get encoding { |
+ return headers.contentType != null ? headers.contentType.encoding |
+ : Encoding.ISO_8859_1; |
+ } |
+ void set encoding(Encoding value) { |
+ throw new StateError("IOSink encoding is not mutable"); |
+ } |
+ |
+ void write(Object obj) { |
_writeHeaders(); |
- if (_ignoreBody) return new Future.immediate(this); |
+ if (_ignoreBody) return; |
+ // This comment is copied from runtime/lib/string_buffer_patch.dart. |
+ // TODO(srdjan): The following four lines could be replaced by |
+ // '$obj', but apparently this is too slow on the Dart VM. |
+ String string; |
+ if (obj is String) { |
+ string = obj; |
+ } else { |
+ string = obj.toString(); |
+ if (string is! String) { |
+ throw new ArgumentError('toString() did not return a string'); |
+ } |
+ } |
+ if (string.isEmpty) return; |
if (_chunked) { |
- // Transform when chunked. |
- stream = stream.transform(new _ChunkedTransformer()); |
+ _ChunkedTransformer._addChunk(_encodeString(string, encoding), |
+ _ioSink.writeBytes); |
+ } else { |
+ _ioSink.write(string); |
} |
- return _ioSink.consume(stream).then((_) => this); |
} |
- void add(List<int> data) { |
+ void writeAll(Iterable objects) { |
+ for (Object obj in objects) write(obj); |
+ } |
+ |
+ void writeln(Object obj) { |
+ write(obj); |
+ write("\n"); |
+ } |
+ |
+ void writeCharCode(int charCode) { |
+ write(new String.fromCharCode(charCode)); |
+ } |
+ |
+ void writeBytes(List<int> data) { |
_writeHeaders(); |
if (_ignoreBody || data.length == 0) return; |
if (_chunked) { |
- _ChunkedTransformer._addChunk(data, _ioSink.add); |
+ _ChunkedTransformer._addChunk(data, _ioSink.writeBytes); |
} else { |
- _ioSink.add(data); |
+ _ioSink.writeBytes(data); |
+ } |
+ } |
+ |
+ Future<T> consume(Stream<List<int>> stream) { |
+ _writeHeaders(); |
+ if (_ignoreBody) return new Future.immediate(this); |
+ if (_chunked) { |
+ // Transform when chunked. |
+ stream = stream.transform(new _ChunkedTransformer()); |
} |
+ return _ioSink.consume(stream).then((_) => this); |
} |
+ void add(List<int> data) => writeBytes(data); |
+ |
void addString(String string, [Encoding encoding = Encoding.UTF_8]) { |
- add(_encodeString(string, encoding)); |
+ writeBytes(_encodeString(string, encoding)); |
} |
Future<T> addStream(Stream<List<int>> stream) { |
@@ -388,7 +435,7 @@ abstract class _HttpOutboundMessage<T> implements IOSink { |
_writeHeaders(); |
if (!_ignoreBody) { |
if (_chunked) { |
- _ChunkedTransformer._addChunk([], _ioSink.add); |
+ _ChunkedTransformer._addChunk([], _ioSink.writeBytes); |
} |
} |
_ioSink.close(); |
@@ -401,7 +448,11 @@ abstract class _HttpOutboundMessage<T> implements IOSink { |
bool _tmpIgnoreBody = _ignoreBody; |
_ignoreBody = false; |
_headersWritten = true; |
+ _ioSink.encoding = Encoding.ASCII; |
_writeHeader(); |
+ _ioSink.encoding = |
+ headers.contentType != null ? headers.contentType.encoding |
+ : Encoding.ISO_8859_1; |
_ignoreBody = _tmpIgnoreBody; |
if (_ignoreBody) { |
_ioSink.close(); |
@@ -455,19 +506,19 @@ class _HttpResponse extends _HttpOutboundMessage<HttpResponse> |
HttpConnectionInfo get connectionInfo => _httpRequest.connectionInfo; |
void _writeHeader() { |
- writeSP() => add([_CharCode.SP]); |
- writeCRLF() => add([_CharCode.CR, _CharCode.LF]); |
+ writeSP() => writeBytes([_CharCode.SP]); |
+ writeCRLF() => writeBytes([_CharCode.CR, _CharCode.LF]); |
// Write status line. |
if (headers.protocolVersion == "1.1") { |
- add(_Const.HTTP11); |
+ writeBytes(_Const.HTTP11); |
} else { |
- add(_Const.HTTP10); |
+ writeBytes(_Const.HTTP10); |
} |
writeSP(); |
- addString(statusCode.toString()); |
+ write(statusCode.toString()); |
writeSP(); |
- addString(reasonPhrase); |
+ write(reasonPhrase); |
writeCRLF(); |
var session = _httpRequest._session; |
@@ -648,10 +699,10 @@ class _HttpClientRequest extends _HttpOutboundMessage<HttpClientRequest> |
} |
void _writeHeader() { |
- writeSP() => add([_CharCode.SP]); |
- writeCRLF() => add([_CharCode.CR, _CharCode.LF]); |
+ writeSP() => writeBytes([_CharCode.SP]); |
+ writeCRLF() => writeBytes([_CharCode.CR, _CharCode.LF]); |
- addString(method); |
+ write(method); |
writeSP(); |
// Send the path for direct connections and the whole URL for |
// proxy connections. |
@@ -665,12 +716,12 @@ class _HttpClientRequest extends _HttpOutboundMessage<HttpClientRequest> |
path = "${path}?${uri.query}"; |
} |
} |
- addString(path); |
+ write(path); |
} else { |
- addString(uri.toString()); |
+ write(uri.toString()); |
} |
writeSP(); |
- add(_Const.HTTP11); |
+ writeBytes(_Const.HTTP11); |
writeCRLF(); |
// Add the cookies to the headers. |
@@ -778,7 +829,8 @@ class _DataValidatorTransformer |
_controller.signalError(new HttpException( |
"Content size exceeds specified contentLength. " |
"$_bytesWritten bytes written while expected " |
- "$expectedTransferLength.")); |
+ "$expectedTransferLength. " |
+ "[${new String.fromCharCodes(data)}]")); |
_controller.close(); |
return; |
} |
@@ -1512,6 +1564,16 @@ class _DetachedSocket extends Stream<List<int>> implements Socket { |
unsubscribeOnError: unsubscribeOnError); |
} |
+ Encoding get encoding => _socket.encoding; |
+ void set encoding(Encoding value) => _socket.encoding = value; |
+ |
+ void write(Object obj) => _socket.write(obj); |
+ void writeln(Object obj) => _socket.writeln(obj); |
+ void writeCharCode(int charCode) => _socket.writeCharCode(charCode); |
+ void writeAll(Iterable objects) => _socket.writeAll(objects); |
+ |
Mads Ager (google)
2013/03/07 07:57:36
Nit: consistently have blank line between write me
Søren Gjesse
2013/03/07 16:28:47
Done.
|
+ void writeBytes(List<int> bytes) => _socket.writeBytes(bytes); |
+ |
Future<Socket> consume(Stream<List<int>> stream) { |
return _socket.consume(stream); |
} |