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 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 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
679 } | 679 } |
680 } | 680 } |
681 | 681 |
682 | 682 |
683 class _HttpResponse extends _HttpOutboundMessage<HttpResponse> | 683 class _HttpResponse extends _HttpOutboundMessage<HttpResponse> |
684 implements HttpResponse { | 684 implements HttpResponse { |
685 int statusCode = 200; | 685 int statusCode = 200; |
686 String _reasonPhrase; | 686 String _reasonPhrase; |
687 List<Cookie> _cookies; | 687 List<Cookie> _cookies; |
688 _HttpRequest _httpRequest; | 688 _HttpRequest _httpRequest; |
| 689 Duration _deadline; |
| 690 Timer _deadlineTimer; |
689 | 691 |
690 _HttpResponse(Uri uri, | 692 _HttpResponse(Uri uri, |
691 String protocolVersion, | 693 String protocolVersion, |
692 _HttpOutgoing _outgoing, | 694 _HttpOutgoing outgoing, |
693 String serverHeader) | 695 String serverHeader) |
694 : super(uri, protocolVersion, _outgoing) { | 696 : super(uri, protocolVersion, outgoing) { |
695 if (serverHeader != null) headers.set('Server', serverHeader); | 697 if (serverHeader != null) headers.set('Server', serverHeader); |
696 } | 698 } |
697 | 699 |
698 List<Cookie> get cookies { | 700 List<Cookie> get cookies { |
699 if (_cookies == null) _cookies = new List<Cookie>(); | 701 if (_cookies == null) _cookies = new List<Cookie>(); |
700 return _cookies; | 702 return _cookies; |
701 } | 703 } |
702 | 704 |
703 String get reasonPhrase => _findReasonPhrase(statusCode); | 705 String get reasonPhrase => _findReasonPhrase(statusCode); |
704 void set reasonPhrase(String reasonPhrase) { | 706 void set reasonPhrase(String reasonPhrase) { |
705 if (_headersWritten) throw new StateError("Header already sent"); | 707 if (_headersWritten) throw new StateError("Header already sent"); |
706 _reasonPhrase = reasonPhrase; | 708 _reasonPhrase = reasonPhrase; |
707 } | 709 } |
708 | 710 |
709 Future<Socket> detachSocket() { | 711 Future<Socket> detachSocket() { |
710 if (_headersWritten) throw new StateError("Headers already sent"); | 712 if (_headersWritten) throw new StateError("Headers already sent"); |
| 713 deadline = null; // Be sure to stop any deadline. |
711 var future = _httpRequest._httpConnection.detachSocket(); | 714 var future = _httpRequest._httpConnection.detachSocket(); |
712 _writeHeaders(drainRequest: false).then((_) => close()); | 715 _writeHeaders(drainRequest: false).then((_) => close()); |
713 // Close connection so the socket is 'free'. | 716 // Close connection so the socket is 'free'. |
714 close(); | 717 close(); |
715 done.catchError((_) { | 718 done.catchError((_) { |
716 // Catch any error on done, as they automatically will be | 719 // Catch any error on done, as they automatically will be |
717 // propagated to the websocket. | 720 // propagated to the websocket. |
718 }); | 721 }); |
719 return future; | 722 return future; |
720 } | 723 } |
721 | 724 |
722 HttpConnectionInfo get connectionInfo => _httpRequest.connectionInfo; | 725 HttpConnectionInfo get connectionInfo => _httpRequest.connectionInfo; |
723 | 726 |
| 727 Duration get deadline => _deadline; |
| 728 |
| 729 void set deadline(Duration d) { |
| 730 if (_deadlineTimer != null) _deadlineTimer.cancel(); |
| 731 _deadline = d; |
| 732 |
| 733 if (_deadline == null) return; |
| 734 _deadlineTimer = new Timer(_deadline, () { |
| 735 _outgoing.socket.destroy(); |
| 736 }); |
| 737 } |
| 738 |
724 void _writeHeader() { | 739 void _writeHeader() { |
725 var builder = new BytesBuilder(); | 740 var builder = new BytesBuilder(); |
726 writeSP() => builder.add(const [_CharCode.SP]); | 741 writeSP() => builder.add(const [_CharCode.SP]); |
727 writeCRLF() => builder.add(const [_CharCode.CR, _CharCode.LF]); | 742 writeCRLF() => builder.add(const [_CharCode.CR, _CharCode.LF]); |
728 | 743 |
729 // Write status line. | 744 // Write status line. |
730 if (headers.protocolVersion == "1.1") { | 745 if (headers.protocolVersion == "1.1") { |
731 builder.add(_Const.HTTP11); | 746 builder.add(_Const.HTTP11); |
732 } else { | 747 } else { |
733 builder.add(_Const.HTTP10); | 748 builder.add(_Const.HTTP10); |
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1091 uri: uri)); | 1106 uri: uri)); |
1092 } | 1107 } |
1093 sink.close(); | 1108 sink.close(); |
1094 } | 1109 } |
1095 } | 1110 } |
1096 | 1111 |
1097 | 1112 |
1098 // Extends StreamConsumer as this is an internal type, only used to pipe to. | 1113 // Extends StreamConsumer as this is an internal type, only used to pipe to. |
1099 class _HttpOutgoing implements StreamConsumer<List<int>> { | 1114 class _HttpOutgoing implements StreamConsumer<List<int>> { |
1100 final Completer _doneCompleter = new Completer(); | 1115 final Completer _doneCompleter = new Completer(); |
1101 final StreamConsumer _consumer; | 1116 final Socket socket; |
1102 | 1117 |
1103 _HttpOutgoing(StreamConsumer this._consumer); | 1118 _HttpOutgoing(Socket this.socket); |
1104 | 1119 |
1105 Future addStream(Stream<List<int>> stream) { | 1120 Future addStream(Stream<List<int>> stream) { |
1106 return _consumer.addStream(stream) | 1121 return socket.addStream(stream) |
1107 .catchError((error) { | 1122 .catchError((error) { |
1108 _doneCompleter.completeError(error); | 1123 _doneCompleter.completeError(error); |
1109 throw error; | 1124 throw error; |
1110 }); | 1125 }); |
1111 } | 1126 } |
1112 | 1127 |
1113 Future close() { | 1128 Future close() { |
1114 _doneCompleter.complete(_consumer); | 1129 _doneCompleter.complete(socket); |
1115 return new Future.value(); | 1130 return new Future.value(); |
1116 } | 1131 } |
1117 | 1132 |
1118 Future get done => _doneCompleter.future; | 1133 Future get done => _doneCompleter.future; |
1119 } | 1134 } |
1120 | 1135 |
1121 class _HttpClientConnection { | 1136 class _HttpClientConnection { |
1122 final String key; | 1137 final String key; |
1123 final Socket _socket; | 1138 final Socket _socket; |
1124 final bool _proxyTunnel; | 1139 final bool _proxyTunnel; |
(...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1805 _subscription.pause(); | 1820 _subscription.pause(); |
1806 _state = _ACTIVE; | 1821 _state = _ACTIVE; |
1807 var outgoing = new _HttpOutgoing(_socket); | 1822 var outgoing = new _HttpOutgoing(_socket); |
1808 var response = new _HttpResponse(incoming.uri, | 1823 var response = new _HttpResponse(incoming.uri, |
1809 incoming.headers.protocolVersion, | 1824 incoming.headers.protocolVersion, |
1810 outgoing, | 1825 outgoing, |
1811 _httpServer.serverHeader); | 1826 _httpServer.serverHeader); |
1812 var request = new _HttpRequest(response, incoming, _httpServer, this); | 1827 var request = new _HttpRequest(response, incoming, _httpServer, this); |
1813 _streamFuture = outgoing.done | 1828 _streamFuture = outgoing.done |
1814 .then((_) { | 1829 .then((_) { |
| 1830 response.deadline = null; |
1815 if (_state == _DETACHED) return; | 1831 if (_state == _DETACHED) return; |
1816 if (response.persistentConnection && | 1832 if (response.persistentConnection && |
1817 request.persistentConnection && | 1833 request.persistentConnection && |
1818 incoming.fullBodyRead) { | 1834 incoming.fullBodyRead) { |
1819 _state = _IDLE; | 1835 _state = _IDLE; |
1820 // Resume the subscription for incoming requests as the | 1836 // Resume the subscription for incoming requests as the |
1821 // request is now processed. | 1837 // request is now processed. |
1822 _subscription.resume(); | 1838 _subscription.resume(); |
1823 } else { | 1839 } else { |
1824 // Close socket, keep-alive not used or body sent before | 1840 // Close socket, keep-alive not used or body sent before |
(...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2408 final Uri location; | 2424 final Uri location; |
2409 } | 2425 } |
2410 | 2426 |
2411 String _getHttpVersion() { | 2427 String _getHttpVersion() { |
2412 var version = Platform.version; | 2428 var version = Platform.version; |
2413 // Only include major and minor version numbers. | 2429 // Only include major and minor version numbers. |
2414 int index = version.indexOf('.', version.indexOf('.') + 1); | 2430 int index = version.indexOf('.', version.indexOf('.') + 1); |
2415 version = version.substring(0, index); | 2431 version = version.substring(0, index); |
2416 return 'Dart/$version (dart:io)'; | 2432 return 'Dart/$version (dart:io)'; |
2417 } | 2433 } |
OLD | NEW |