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

Side by Side Diff: sdk/lib/io/http_impl.dart

Issue 12504006: Make IOSink implement StringSink (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Correct rebase Created 7 years, 9 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
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 part of dart.io; 5 part of dart.io;
6 6
7 class _HttpIncoming extends Stream<List<int>> { 7 class _HttpIncoming extends Stream<List<int>> {
8 final int _transferLength; 8 final int _transferLength;
9 final Completer _dataCompleter = new Completer(); 9 final Completer _dataCompleter = new Completer();
10 Stream<List<int>> _stream; 10 Stream<List<int>> _stream;
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 bool _headersWritten = false; 325 bool _headersWritten = false;
326 bool _chunked = false; 326 bool _chunked = false;
327 327
328 final IOSink _ioSink; 328 final IOSink _ioSink;
329 final _HttpOutgoing _outgoing; 329 final _HttpOutgoing _outgoing;
330 330
331 final _HttpHeaders headers; 331 final _HttpHeaders headers;
332 332
333 _HttpOutboundMessage(String protocolVersion, _HttpOutgoing outgoing) 333 _HttpOutboundMessage(String protocolVersion, _HttpOutgoing outgoing)
334 : _outgoing = outgoing, 334 : _outgoing = outgoing,
335 _ioSink = new IOSink(outgoing), 335 _ioSink = new IOSink(outgoing, Encoding.ASCII),
336 headers = new _HttpHeaders(protocolVersion); 336 headers = new _HttpHeaders(protocolVersion);
337 337
338 int get contentLength => headers.contentLength; 338 int get contentLength => headers.contentLength;
339 void set contentLength(int contentLength) { 339 void set contentLength(int contentLength) {
340 headers.contentLength = contentLength; 340 headers.contentLength = contentLength;
341 } 341 }
342 342
343 bool get persistentConnection => headers.persistentConnection; 343 bool get persistentConnection => headers.persistentConnection;
344 void set persistentConnection(bool p) { 344 void set persistentConnection(bool p) {
345 headers.persistentConnection = p; 345 headers.persistentConnection = p;
346 } 346 }
347 347
348 Encoding get encoding {
349 return headers.contentType != null ? headers.contentType.encoding
350 : Encoding.ISO_8859_1;
351 }
352 void set encoding(Encoding value) {
353 throw new StateError("IOSink encoding is not mutable");
354 }
355
356 void write(Object obj) {
357 _writeHeaders();
358 if (_ignoreBody) return;
359 // This comment is copied from runtime/lib/string_buffer_patch.dart.
360 // TODO(srdjan): The following four lines could be replaced by
361 // '$obj', but apparently this is too slow on the Dart VM.
362 String string;
363 if (obj is String) {
364 string = obj;
365 } else {
366 string = obj.toString();
367 if (string is! String) {
368 throw new ArgumentError('toString() did not return a string');
369 }
370 }
371 if (string.isEmpty) return;
372 if (_chunked) {
373 _ChunkedTransformer._addChunk(_encodeString(string, encoding),
374 _ioSink.writeBytes);
375 } else {
376 _ioSink.write(string);
377 }
378 }
379
380 void writeAll(Iterable objects) {
381 for (Object obj in objects) write(obj);
382 }
383
384 void writeln(Object obj) {
385 write(obj);
386 write("\n");
387 }
388
389 void writeCharCode(int charCode) {
390 write(new String.fromCharCode(charCode));
391 }
392
393 void writeBytes(List<int> data) {
394 _writeHeaders();
395 if (_ignoreBody || data.length == 0) return;
396 if (_chunked) {
397 _ChunkedTransformer._addChunk(data, _ioSink.writeBytes);
398 } else {
399 _ioSink.writeBytes(data);
400 }
401 }
402
348 Future<T> consume(Stream<List<int>> stream) { 403 Future<T> consume(Stream<List<int>> stream) {
349 _writeHeaders(); 404 _writeHeaders();
350 if (_ignoreBody) return new Future.immediate(this); 405 if (_ignoreBody) return new Future.immediate(this);
351 if (_chunked) { 406 if (_chunked) {
352 // Transform when chunked. 407 // Transform when chunked.
353 stream = stream.transform(new _ChunkedTransformer()); 408 stream = stream.transform(new _ChunkedTransformer());
354 } 409 }
355 return _ioSink.consume(stream).then((_) => this); 410 return _ioSink.consume(stream).then((_) => this);
356 } 411 }
357 412
358 void add(List<int> data) { 413 void add(List<int> data) => writeBytes(data);
359 _writeHeaders();
360 if (_ignoreBody || data.length == 0) return;
361 if (_chunked) {
362 _ChunkedTransformer._addChunk(data, _ioSink.add);
363 } else {
364 _ioSink.add(data);
365 }
366 }
367 414
368 void addString(String string, [Encoding encoding = Encoding.UTF_8]) { 415 void addString(String string, [Encoding encoding = Encoding.UTF_8]) {
369 add(_encodeString(string, encoding)); 416 writeBytes(_encodeString(string, encoding));
370 } 417 }
371 418
372 Future<T> addStream(Stream<List<int>> stream) { 419 Future<T> addStream(Stream<List<int>> stream) {
373 _writeHeaders(); 420 _writeHeaders();
374 if (_ignoreBody) return new Future.immediate(this); 421 if (_ignoreBody) return new Future.immediate(this);
375 if (_chunked) { 422 if (_chunked) {
376 // Transform when chunked. 423 // Transform when chunked.
377 stream = stream.transform(new _ChunkedTransformer(writeEnd: false)); 424 stream = stream.transform(new _ChunkedTransformer(writeEnd: false));
378 } 425 }
379 return _ioSink.addStream(stream).then((_) => this); 426 return _ioSink.addStream(stream).then((_) => this);
380 } 427 }
381 428
382 void close() { 429 void close() {
383 if (!_headersWritten && !_ignoreBody && headers.chunkedTransferEncoding) { 430 if (!_headersWritten && !_ignoreBody && headers.chunkedTransferEncoding) {
384 // If no body was written, _ignoreBody is false (it's not a HEAD 431 // If no body was written, _ignoreBody is false (it's not a HEAD
385 // request) and the content-length is unspecified, set contentLength to 0. 432 // request) and the content-length is unspecified, set contentLength to 0.
386 headers.contentLength = 0; 433 headers.contentLength = 0;
387 } 434 }
388 _writeHeaders(); 435 _writeHeaders();
389 if (!_ignoreBody) { 436 if (!_ignoreBody) {
390 if (_chunked) { 437 if (_chunked) {
391 _ChunkedTransformer._addChunk([], _ioSink.add); 438 _ChunkedTransformer._addChunk([], _ioSink.writeBytes);
392 } 439 }
393 } 440 }
394 _ioSink.close(); 441 _ioSink.close();
395 } 442 }
396 443
397 Future<T> get done => _ioSink.done.then((_) => this); 444 Future<T> get done => _ioSink.done.then((_) => this);
398 445
399 void _writeHeaders() { 446 void _writeHeaders() {
400 if (_headersWritten) return; 447 if (_headersWritten) return;
401 bool _tmpIgnoreBody = _ignoreBody; 448 bool _tmpIgnoreBody = _ignoreBody;
402 _ignoreBody = false; 449 _ignoreBody = false;
403 _headersWritten = true; 450 _headersWritten = true;
451 _ioSink.encoding = Encoding.ASCII;
404 _writeHeader(); 452 _writeHeader();
453 _ioSink.encoding =
454 headers.contentType != null ? headers.contentType.encoding
455 : Encoding.ISO_8859_1;
405 _ignoreBody = _tmpIgnoreBody; 456 _ignoreBody = _tmpIgnoreBody;
406 if (_ignoreBody) { 457 if (_ignoreBody) {
407 _ioSink.close(); 458 _ioSink.close();
408 return; 459 return;
409 } 460 }
410 _chunked = headers.chunkedTransferEncoding; 461 _chunked = headers.chunkedTransferEncoding;
411 if (headers.contentLength >= 0) { 462 if (headers.contentLength >= 0) {
412 _outgoing.setTransferLength(headers.contentLength); 463 _outgoing.setTransferLength(headers.contentLength);
413 } 464 }
414 } 465 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
448 done.catchError((_) { 499 done.catchError((_) {
449 // Catch any error on done, as they automatically will be propegated to 500 // Catch any error on done, as they automatically will be propegated to
450 // the websocket. 501 // the websocket.
451 }); 502 });
452 return future; 503 return future;
453 } 504 }
454 505
455 HttpConnectionInfo get connectionInfo => _httpRequest.connectionInfo; 506 HttpConnectionInfo get connectionInfo => _httpRequest.connectionInfo;
456 507
457 void _writeHeader() { 508 void _writeHeader() {
458 writeSP() => add([_CharCode.SP]); 509 writeSP() => writeBytes([_CharCode.SP]);
459 writeCRLF() => add([_CharCode.CR, _CharCode.LF]); 510 writeCRLF() => writeBytes([_CharCode.CR, _CharCode.LF]);
460 511
461 // Write status line. 512 // Write status line.
462 if (headers.protocolVersion == "1.1") { 513 if (headers.protocolVersion == "1.1") {
463 add(_Const.HTTP11); 514 writeBytes(_Const.HTTP11);
464 } else { 515 } else {
465 add(_Const.HTTP10); 516 writeBytes(_Const.HTTP10);
466 } 517 }
467 writeSP(); 518 writeSP();
468 addString(statusCode.toString()); 519 write(statusCode.toString());
469 writeSP(); 520 writeSP();
470 addString(reasonPhrase); 521 write(reasonPhrase);
471 writeCRLF(); 522 writeCRLF();
472 523
473 var session = _httpRequest._session; 524 var session = _httpRequest._session;
474 if (session != null && !session._destroyed) { 525 if (session != null && !session._destroyed) {
475 // Mark as not new. 526 // Mark as not new.
476 session._isNew = false; 527 session._isNew = false;
477 // Make sure we only send the current session id. 528 // Make sure we only send the current session id.
478 bool found = false; 529 bool found = false;
479 for (int i = 0; i < cookies.length; i++) { 530 for (int i = 0; i < cookies.length; i++) {
480 if (cookies[i].name.toUpperCase() == _DART_SESSION_ID) { 531 if (cookies[i].name.toUpperCase() == _DART_SESSION_ID) {
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
641 onError: (e) { 692 onError: (e) {
642 _responseCompleter.completeError(e); 693 _responseCompleter.completeError(e);
643 }); 694 });
644 } 695 }
645 696
646 void _onError(AsyncError error) { 697 void _onError(AsyncError error) {
647 _responseCompleter.completeError(error); 698 _responseCompleter.completeError(error);
648 } 699 }
649 700
650 void _writeHeader() { 701 void _writeHeader() {
651 writeSP() => add([_CharCode.SP]); 702 writeSP() => writeBytes([_CharCode.SP]);
652 writeCRLF() => add([_CharCode.CR, _CharCode.LF]); 703 writeCRLF() => writeBytes([_CharCode.CR, _CharCode.LF]);
653 704
654 addString(method); 705 write(method);
655 writeSP(); 706 writeSP();
656 // Send the path for direct connections and the whole URL for 707 // Send the path for direct connections and the whole URL for
657 // proxy connections. 708 // proxy connections.
658 if (!_usingProxy) { 709 if (!_usingProxy) {
659 String path = uri.path; 710 String path = uri.path;
660 if (path.length == 0) path = "/"; 711 if (path.length == 0) path = "/";
661 if (uri.query != "") { 712 if (uri.query != "") {
662 if (uri.fragment != "") { 713 if (uri.fragment != "") {
663 path = "${path}?${uri.query}#${uri.fragment}"; 714 path = "${path}?${uri.query}#${uri.fragment}";
664 } else { 715 } else {
665 path = "${path}?${uri.query}"; 716 path = "${path}?${uri.query}";
666 } 717 }
667 } 718 }
668 addString(path); 719 write(path);
669 } else { 720 } else {
670 addString(uri.toString()); 721 write(uri.toString());
671 } 722 }
672 writeSP(); 723 writeSP();
673 add(_Const.HTTP11); 724 writeBytes(_Const.HTTP11);
674 writeCRLF(); 725 writeCRLF();
675 726
676 // Add the cookies to the headers. 727 // Add the cookies to the headers.
677 if (!cookies.isEmpty) { 728 if (!cookies.isEmpty) {
678 StringBuffer sb = new StringBuffer(); 729 StringBuffer sb = new StringBuffer();
679 for (int i = 0; i < cookies.length; i++) { 730 for (int i = 0; i < cookies.length; i++) {
680 if (i > 0) sb.write("; "); 731 if (i > 0) sb.write("; ");
681 sb.write(cookies[i].name); 732 sb.write(cookies[i].name);
682 sb.write("="); 733 sb.write("=");
683 sb.write(cookies[i].value); 734 sb.write(cookies[i].value);
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
771 var subscription; 822 var subscription;
772 subscription = stream.listen( 823 subscription = stream.listen(
773 (data) { 824 (data) {
774 if (expectedTransferLength != null) { 825 if (expectedTransferLength != null) {
775 _bytesWritten += data.length; 826 _bytesWritten += data.length;
776 if (_bytesWritten > expectedTransferLength) { 827 if (_bytesWritten > expectedTransferLength) {
777 subscription.cancel(); 828 subscription.cancel();
778 _controller.signalError(new HttpException( 829 _controller.signalError(new HttpException(
779 "Content size exceeds specified contentLength. " 830 "Content size exceeds specified contentLength. "
780 "$_bytesWritten bytes written while expected " 831 "$_bytesWritten bytes written while expected "
781 "$expectedTransferLength.")); 832 "$expectedTransferLength. "
833 "[${new String.fromCharCodes(data)}]"));
782 _controller.close(); 834 _controller.close();
783 return; 835 return;
784 } 836 }
785 } 837 }
786 _controller.add(data); 838 _controller.add(data);
787 }, 839 },
788 onError: (error) { 840 onError: (error) {
789 _controller.signalError(error); 841 _controller.signalError(error);
790 _controller.close(); 842 _controller.close();
791 }, 843 },
(...skipping 713 matching lines...) Expand 10 before | Expand all | Expand 10 after
1505 StreamSubscription<List<int>> listen(void onData(List<int> event), 1557 StreamSubscription<List<int>> listen(void onData(List<int> event),
1506 {void onError(AsyncError error), 1558 {void onError(AsyncError error),
1507 void onDone(), 1559 void onDone(),
1508 bool unsubscribeOnError}) { 1560 bool unsubscribeOnError}) {
1509 return _incoming.listen(onData, 1561 return _incoming.listen(onData,
1510 onError: onError, 1562 onError: onError,
1511 onDone: onDone, 1563 onDone: onDone,
1512 unsubscribeOnError: unsubscribeOnError); 1564 unsubscribeOnError: unsubscribeOnError);
1513 } 1565 }
1514 1566
1567 Encoding get encoding => _socket.encoding;
1568 void set encoding(Encoding value) => _socket.encoding = value;
1569
1570 void write(Object obj) => _socket.write(obj);
1571 void writeln(Object obj) => _socket.writeln(obj);
1572 void writeCharCode(int charCode) => _socket.writeCharCode(charCode);
1573 void writeAll(Iterable objects) => _socket.writeAll(objects);
1574
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.
1575 void writeBytes(List<int> bytes) => _socket.writeBytes(bytes);
1576
1515 Future<Socket> consume(Stream<List<int>> stream) { 1577 Future<Socket> consume(Stream<List<int>> stream) {
1516 return _socket.consume(stream); 1578 return _socket.consume(stream);
1517 } 1579 }
1518 1580
1519 Future<Socket> addStream(Stream<List<int>> stream) { 1581 Future<Socket> addStream(Stream<List<int>> stream) {
1520 return _socket.addStream(stream); 1582 return _socket.addStream(stream);
1521 } 1583 }
1522 1584
1523 void addString(String string, [Encoding encoding = Encoding.UTF_8]) { 1585 void addString(String string, [Encoding encoding = Encoding.UTF_8]) {
1524 return _socket.addString(string, encoding); 1586 return _socket.addString(string, encoding);
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
1639 1701
1640 1702
1641 class _RedirectInfo implements RedirectInfo { 1703 class _RedirectInfo implements RedirectInfo {
1642 const _RedirectInfo(int this.statusCode, 1704 const _RedirectInfo(int this.statusCode,
1643 String this.method, 1705 String this.method,
1644 Uri this.location); 1706 Uri this.location);
1645 final int statusCode; 1707 final int statusCode;
1646 final String method; 1708 final String method;
1647 final Uri location; 1709 final Uri location;
1648 } 1710 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698