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

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: Addressed second round of review comments 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
« no previous file with comments | « sdk/lib/io/http_headers.dart ('k') | sdk/lib/io/io_sink.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 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: 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 var charset;
350 if (headers.contentType != null && headers.contentType.charset != null) {
351 charset = headers.contentType.charset;
352 } else {
353 charset = "iso-8859-1";
354 }
355 return Encoding.fromName(charset);
356 }
357
358 void set encoding(Encoding value) {
359 throw new StateError("IOSink encoding is not mutable");
360 }
361
362 void write(Object obj) {
363 _writeHeaders();
364 if (_ignoreBody) return;
365 // This comment is copied from runtime/lib/string_buffer_patch.dart.
366 // TODO(srdjan): The following four lines could be replaced by
367 // '$obj', but apparently this is too slow on the Dart VM.
368 String string;
369 if (obj is String) {
370 string = obj;
371 } else {
372 string = obj.toString();
373 if (string is! String) {
374 throw new ArgumentError('toString() did not return a string');
375 }
376 }
377 if (string.isEmpty) return;
378 if (_chunked) {
379 _ChunkedTransformer._addChunk(_encodeString(string, encoding),
380 _ioSink.writeBytes);
381 } else {
382 _ioSink.write(string);
383 }
384 }
385
386 void writeAll(Iterable objects) {
387 for (Object obj in objects) write(obj);
388 }
389
390 void writeln(Object obj) {
391 write(obj);
392 write("\n");
393 }
394
395 void writeCharCode(int charCode) {
396 write(new String.fromCharCode(charCode));
397 }
398
399 void writeBytes(List<int> data) {
400 _writeHeaders();
401 if (_ignoreBody || data.length == 0) return;
402 if (_chunked) {
403 _ChunkedTransformer._addChunk(data, _ioSink.writeBytes);
404 } else {
405 _ioSink.writeBytes(data);
406 }
407 }
408
348 Future<T> consume(Stream<List<int>> stream) { 409 Future<T> consume(Stream<List<int>> stream) {
349 _writeHeaders(); 410 _writeHeaders();
350 if (_ignoreBody) return new Future.immediate(this); 411 if (_ignoreBody) return new Future.immediate(this);
351 if (_chunked) { 412 if (_chunked) {
352 // Transform when chunked. 413 // Transform when chunked.
353 stream = stream.transform(new _ChunkedTransformer()); 414 stream = stream.transform(new _ChunkedTransformer());
354 } 415 }
355 return _ioSink.consume(stream).then((_) => this); 416 return _ioSink.consume(stream).then((_) => this);
356 } 417 }
357 418
358 void add(List<int> data) { 419 Future<T> writeStream(Stream<List<int>> stream) {
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
368 void addString(String string, [Encoding encoding = Encoding.UTF_8]) {
369 add(_encodeString(string, encoding));
370 }
371
372 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.writeStream(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 _headersWritten = true; 448 _headersWritten = true;
449 _ioSink.encoding = Encoding.ASCII;
402 _writeHeader(); 450 _writeHeader();
451 _ioSink.encoding = encoding;
403 if (_ignoreBody) { 452 if (_ignoreBody) {
404 _ioSink.close(); 453 _ioSink.close();
405 return; 454 return;
406 } 455 }
407 _chunked = headers.chunkedTransferEncoding; 456 _chunked = headers.chunkedTransferEncoding;
408 if (headers.contentLength >= 0) { 457 if (headers.contentLength >= 0) {
409 _outgoing.setTransferLength(headers.contentLength); 458 _outgoing.setTransferLength(headers.contentLength);
410 } 459 }
411 } 460 }
412 461
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 done.catchError((_) { 494 done.catchError((_) {
446 // Catch any error on done, as they automatically will be propegated to 495 // Catch any error on done, as they automatically will be propegated to
447 // the websocket. 496 // the websocket.
448 }); 497 });
449 return future; 498 return future;
450 } 499 }
451 500
452 HttpConnectionInfo get connectionInfo => _httpRequest.connectionInfo; 501 HttpConnectionInfo get connectionInfo => _httpRequest.connectionInfo;
453 502
454 void _writeHeader() { 503 void _writeHeader() {
455 writeSP() => _ioSink.add([_CharCode.SP]); 504 writeSP() => _ioSink.writeBytes([_CharCode.SP]);
456 writeCRLF() => _ioSink.add([_CharCode.CR, _CharCode.LF]); 505 writeCRLF() => _ioSink.writeBytes([_CharCode.CR, _CharCode.LF]);
457 506
458 // Write status line. 507 // Write status line.
459 if (headers.protocolVersion == "1.1") { 508 if (headers.protocolVersion == "1.1") {
460 _ioSink.add(_Const.HTTP11); 509 _ioSink.writeBytes(_Const.HTTP11);
461 } else { 510 } else {
462 _ioSink.add(_Const.HTTP10); 511 _ioSink.writeBytes(_Const.HTTP10);
463 } 512 }
464 writeSP(); 513 writeSP();
465 _ioSink.addString(statusCode.toString()); 514 _ioSink.write(statusCode.toString());
466 writeSP(); 515 writeSP();
467 _ioSink.addString(reasonPhrase); 516 _ioSink.write(reasonPhrase);
468 writeCRLF(); 517 writeCRLF();
469 518
470 var session = _httpRequest._session; 519 var session = _httpRequest._session;
471 if (session != null && !session._destroyed) { 520 if (session != null && !session._destroyed) {
472 // Mark as not new. 521 // Mark as not new.
473 session._isNew = false; 522 session._isNew = false;
474 // Make sure we only send the current session id. 523 // Make sure we only send the current session id.
475 bool found = false; 524 bool found = false;
476 for (int i = 0; i < cookies.length; i++) { 525 for (int i = 0; i < cookies.length; i++) {
477 if (cookies[i].name.toUpperCase() == _DART_SESSION_ID) { 526 if (cookies[i].name.toUpperCase() == _DART_SESSION_ID) {
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
638 onError: (e) { 687 onError: (e) {
639 _responseCompleter.completeError(e); 688 _responseCompleter.completeError(e);
640 }); 689 });
641 } 690 }
642 691
643 void _onError(AsyncError error) { 692 void _onError(AsyncError error) {
644 _responseCompleter.completeError(error); 693 _responseCompleter.completeError(error);
645 } 694 }
646 695
647 void _writeHeader() { 696 void _writeHeader() {
648 writeSP() => _ioSink.add([_CharCode.SP]); 697 writeSP() => _ioSink.writeBytes([_CharCode.SP]);
649 writeCRLF() => _ioSink.add([_CharCode.CR, _CharCode.LF]); 698 writeCRLF() => _ioSink.writeBytes([_CharCode.CR, _CharCode.LF]);
650 699
651 _ioSink.addString(method); 700 _ioSink.write(method);
652 writeSP(); 701 writeSP();
653 // Send the path for direct connections and the whole URL for 702 // Send the path for direct connections and the whole URL for
654 // proxy connections. 703 // proxy connections.
655 if (!_usingProxy) { 704 if (!_usingProxy) {
656 String path = uri.path; 705 String path = uri.path;
657 if (path.length == 0) path = "/"; 706 if (path.length == 0) path = "/";
658 if (uri.query != "") { 707 if (uri.query != "") {
659 if (uri.fragment != "") { 708 if (uri.fragment != "") {
660 path = "${path}?${uri.query}#${uri.fragment}"; 709 path = "${path}?${uri.query}#${uri.fragment}";
661 } else { 710 } else {
662 path = "${path}?${uri.query}"; 711 path = "${path}?${uri.query}";
663 } 712 }
664 } 713 }
665 _ioSink.addString(path); 714 _ioSink.write(path);
666 } else { 715 } else {
667 _ioSink.addString(uri.toString()); 716 _ioSink.write(uri.toString());
668 } 717 }
669 writeSP(); 718 writeSP();
670 _ioSink.add(_Const.HTTP11); 719 _ioSink.writeBytes(_Const.HTTP11);
671 writeCRLF(); 720 writeCRLF();
672 721
673 // Add the cookies to the headers. 722 // Add the cookies to the headers.
674 if (!cookies.isEmpty) { 723 if (!cookies.isEmpty) {
675 StringBuffer sb = new StringBuffer(); 724 StringBuffer sb = new StringBuffer();
676 for (int i = 0; i < cookies.length; i++) { 725 for (int i = 0; i < cookies.length; i++) {
677 if (i > 0) sb.write("; "); 726 if (i > 0) sb.write("; ");
678 sb.write(cookies[i].name); 727 sb.write(cookies[i].name);
679 sb.write("="); 728 sb.write("=");
680 sb.write(cookies[i].value); 729 sb.write(cookies[i].value);
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
768 var subscription; 817 var subscription;
769 subscription = stream.listen( 818 subscription = stream.listen(
770 (data) { 819 (data) {
771 if (expectedTransferLength != null) { 820 if (expectedTransferLength != null) {
772 _bytesWritten += data.length; 821 _bytesWritten += data.length;
773 if (_bytesWritten > expectedTransferLength) { 822 if (_bytesWritten > expectedTransferLength) {
774 subscription.cancel(); 823 subscription.cancel();
775 _controller.signalError(new HttpException( 824 _controller.signalError(new HttpException(
776 "Content size exceeds specified contentLength. " 825 "Content size exceeds specified contentLength. "
777 "$_bytesWritten bytes written while expected " 826 "$_bytesWritten bytes written while expected "
778 "$expectedTransferLength.")); 827 "$expectedTransferLength. "
828 "[${new String.fromCharCodes(data)}]"));
779 _controller.close(); 829 _controller.close();
780 return; 830 return;
781 } 831 }
782 } 832 }
783 _controller.add(data); 833 _controller.add(data);
784 }, 834 },
785 onError: (error) { 835 onError: (error) {
786 _controller.signalError(error); 836 _controller.signalError(error);
787 _controller.close(); 837 _controller.close();
788 }, 838 },
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
894 cr.authorize(request); 944 cr.authorize(request);
895 } 945 }
896 } 946 }
897 // Start sending the request (lazy, delayed until the user provides 947 // Start sending the request (lazy, delayed until the user provides
898 // data). 948 // data).
899 _httpParser.responseToMethod = method; 949 _httpParser.responseToMethod = method;
900 _streamFuture = outgoing.onStream((stream) { 950 _streamFuture = outgoing.onStream((stream) {
901 // Sending request, set up response completer. 951 // Sending request, set up response completer.
902 _nextResponseCompleter = new Completer(); 952 _nextResponseCompleter = new Completer();
903 953
904 var requestFuture = _socket.addStream(stream) 954 var requestFuture = _socket.writeStream(stream)
905 .catchError((e) { 955 .catchError((e) {
906 destroy(); 956 destroy();
907 throw e; 957 throw e;
908 }); 958 });
909 959
910 // Listen for response. 960 // Listen for response.
911 _nextResponseCompleter.future 961 _nextResponseCompleter.future
912 .then((incoming) { 962 .then((incoming) {
913 incoming.dataDone.then((_) { 963 incoming.dataDone.then((_) {
914 if (incoming.headers.persistentConnection && 964 if (incoming.headers.persistentConnection &&
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
1221 (incoming) { 1271 (incoming) {
1222 // Only handle one incoming request at the time. Keep the 1272 // Only handle one incoming request at the time. Keep the
1223 // stream paused until the request has been send. 1273 // stream paused until the request has been send.
1224 _subscription.pause(); 1274 _subscription.pause();
1225 _state = _ACTIVE; 1275 _state = _ACTIVE;
1226 var outgoing = new _HttpOutgoing(); 1276 var outgoing = new _HttpOutgoing();
1227 var response = new _HttpResponse(incoming.headers.protocolVersion, 1277 var response = new _HttpResponse(incoming.headers.protocolVersion,
1228 outgoing); 1278 outgoing);
1229 var request = new _HttpRequest(response, incoming, _httpServer, this); 1279 var request = new _HttpRequest(response, incoming, _httpServer, this);
1230 outgoing.onStream((stream) { 1280 outgoing.onStream((stream) {
1231 return _streamFuture = _socket.addStream(stream) 1281 return _streamFuture = _socket.writeStream(stream)
1232 .then((_) { 1282 .then((_) {
1233 if (_state == _DETACHED) return; 1283 if (_state == _DETACHED) return;
1234 if (response.persistentConnection && 1284 if (response.persistentConnection &&
1235 request.persistentConnection && 1285 request.persistentConnection &&
1236 incoming.fullBodyRead) { 1286 incoming.fullBodyRead) {
1237 _state = _IDLE; 1287 _state = _IDLE;
1238 // Resume the subscription for incoming requests as the 1288 // Resume the subscription for incoming requests as the
1239 // request is now processed. 1289 // request is now processed.
1240 _subscription.resume(); 1290 _subscription.resume();
1241 } else { 1291 } else {
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
1502 StreamSubscription<List<int>> listen(void onData(List<int> event), 1552 StreamSubscription<List<int>> listen(void onData(List<int> event),
1503 {void onError(AsyncError error), 1553 {void onError(AsyncError error),
1504 void onDone(), 1554 void onDone(),
1505 bool unsubscribeOnError}) { 1555 bool unsubscribeOnError}) {
1506 return _incoming.listen(onData, 1556 return _incoming.listen(onData,
1507 onError: onError, 1557 onError: onError,
1508 onDone: onDone, 1558 onDone: onDone,
1509 unsubscribeOnError: unsubscribeOnError); 1559 unsubscribeOnError: unsubscribeOnError);
1510 } 1560 }
1511 1561
1562 Encoding get encoding => _socket.encoding;
1563
1564 void set encoding(Encoding value) {
1565 _socket.encoding = value;
1566 }
1567
1568 void write(Object obj) => _socket.write(obj);
1569
1570 void writeln(Object obj) => _socket.writeln(obj);
1571
1572 void writeCharCode(int charCode) => _socket.writeCharCode(charCode);
1573
1574 void writeAll(Iterable objects) => _socket.writeAll(objects);
1575
1576 void writeBytes(List<int> bytes) => _socket.writeBytes(bytes);
1577
1512 Future<Socket> consume(Stream<List<int>> stream) { 1578 Future<Socket> consume(Stream<List<int>> stream) {
1513 return _socket.consume(stream); 1579 return _socket.consume(stream);
1514 } 1580 }
1515 1581
1516 Future<Socket> addStream(Stream<List<int>> stream) { 1582 Future<Socket> writeStream(Stream<List<int>> stream) {
1517 return _socket.addStream(stream); 1583 return _socket.writeStream(stream);
1518 }
1519
1520 void addString(String string, [Encoding encoding = Encoding.UTF_8]) {
1521 return _socket.addString(string, encoding);
1522 } 1584 }
1523 1585
1524 void destroy() => _socket.destroy(); 1586 void destroy() => _socket.destroy();
1525 void add(List<int> data) => _socket.add(data); 1587
1526 void close() => _socket.close(); 1588 void close() => _socket.close();
1589
1527 Future<Socket> get done => _socket.done; 1590 Future<Socket> get done => _socket.done;
1591
1528 int get port => _socket.port; 1592 int get port => _socket.port;
1593
1529 String get remoteHost => _socket.remoteHost; 1594 String get remoteHost => _socket.remoteHost;
1595
1530 int get remotePort => _socket.remotePort; 1596 int get remotePort => _socket.remotePort;
1531 } 1597 }
1532 1598
1533 1599
1534 class _AuthenticationScheme { 1600 class _AuthenticationScheme {
1535 static const UNKNOWN = const _AuthenticationScheme(-1); 1601 static const UNKNOWN = const _AuthenticationScheme(-1);
1536 static const BASIC = const _AuthenticationScheme(0); 1602 static const BASIC = const _AuthenticationScheme(0);
1537 static const DIGEST = const _AuthenticationScheme(1); 1603 static const DIGEST = const _AuthenticationScheme(1);
1538 1604
1539 const _AuthenticationScheme(this._scheme); 1605 const _AuthenticationScheme(this._scheme);
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1636 1702
1637 1703
1638 class _RedirectInfo implements RedirectInfo { 1704 class _RedirectInfo implements RedirectInfo {
1639 const _RedirectInfo(int this.statusCode, 1705 const _RedirectInfo(int this.statusCode,
1640 String this.method, 1706 String this.method,
1641 Uri this.location); 1707 Uri this.location);
1642 final int statusCode; 1708 final int statusCode;
1643 final String method; 1709 final String method;
1644 final Uri location; 1710 final Uri location;
1645 } 1711 }
OLDNEW
« no previous file with comments | « sdk/lib/io/http_headers.dart ('k') | sdk/lib/io/io_sink.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698