| 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 520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 531 // TODO(ajohnsen): Currently, contentLength, chunkedTransferEncoding and | 531 // TODO(ajohnsen): Currently, contentLength, chunkedTransferEncoding and |
| 532 // persistentConnection is not guaranteed to be in sync. | 532 // persistentConnection is not guaranteed to be in sync. |
| 533 if (!_headersWritten) { | 533 if (!_headersWritten) { |
| 534 if (!_ignoreBody && headers.contentLength == -1) { | 534 if (!_ignoreBody && headers.contentLength == -1) { |
| 535 // If no body was written, _ignoreBody is false (it's not a HEAD | 535 // If no body was written, _ignoreBody is false (it's not a HEAD |
| 536 // request) and the content-length is unspecified, set contentLength to | 536 // request) and the content-length is unspecified, set contentLength to |
| 537 // 0. | 537 // 0. |
| 538 headers.chunkedTransferEncoding = false; | 538 headers.chunkedTransferEncoding = false; |
| 539 headers.contentLength = 0; | 539 headers.contentLength = 0; |
| 540 } else if (!_ignoreBody && headers.contentLength > 0) { | 540 } else if (!_ignoreBody && headers.contentLength > 0) { |
| 541 _headersSink.close().catchError((_) {}); | 541 _headersSink.addError(new HttpException( |
| 542 return new Future.error(new HttpException( | |
| 543 "No content while contentLength was specified to be greater " | 542 "No content while contentLength was specified to be greater " |
| 544 " than 0: ${headers.contentLength}.", | 543 "than 0: ${headers.contentLength}.", |
| 545 uri: _uri)); | 544 uri: _uri)); |
| 545 return _headersSink.done; |
| 546 } | 546 } |
| 547 } | 547 } |
| 548 return _writeHeaders().then((_) => _headersSink.close()); | 548 return _writeHeaders().then((_) => _headersSink.close()); |
| 549 } | 549 } |
| 550 | 550 |
| 551 void _writeHeader(); // TODO(ajohnsen): Better name. | 551 void _writeHeader(); // TODO(ajohnsen): Better name. |
| 552 } | 552 } |
| 553 | 553 |
| 554 | 554 |
| 555 class _HttpOutboundConsumer implements StreamConsumer { | 555 class _HttpOutboundConsumer implements StreamConsumer { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 613 | 613 |
| 614 Future addStream(var stream) { | 614 Future addStream(var stream) { |
| 615 // If we saw a socket error subscribe and then cancel, to ignore any data | 615 // If we saw a socket error subscribe and then cancel, to ignore any data |
| 616 // on the stream. | 616 // on the stream. |
| 617 if (_socketError) { | 617 if (_socketError) { |
| 618 stream.listen(null).cancel(); | 618 stream.listen(null).cancel(); |
| 619 return new Future.value(_outbound); | 619 return new Future.value(_outbound); |
| 620 } | 620 } |
| 621 _completer = new Completer(); | 621 _completer = new Completer(); |
| 622 _subscription = stream.listen( | 622 _subscription = stream.listen( |
| 623 (data) { | 623 (data) => _controller.add(data), |
| 624 _controller.add(data); | |
| 625 }, | |
| 626 onDone: _done, | 624 onDone: _done, |
| 627 onError: _done, | 625 onError: (e, s) => _controller.addError(e, s), |
| 628 cancelOnError: true); | 626 cancelOnError: true); |
| 629 // Pause the first request. | 627 // Pause the first request. |
| 630 if (_controller == null) _subscription.pause(); | 628 if (_controller == null) _subscription.pause(); |
| 631 _ensureController(); | 629 _ensureController(); |
| 632 return _completer.future; | 630 return _completer.future; |
| 633 } | 631 } |
| 634 | 632 |
| 635 Future close() { | 633 Future close() { |
| 636 Future closeOutbound() { | 634 Future closeOutbound() { |
| 637 if (_socketError) return new Future.value(_outbound); | 635 if (_socketError) return new Future.value(_outbound); |
| (...skipping 1233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1871 incoming.headers.protocolVersion, | 1869 incoming.headers.protocolVersion, |
| 1872 outgoing, | 1870 outgoing, |
| 1873 _httpServer.serverHeader); | 1871 _httpServer.serverHeader); |
| 1874 var request = new _HttpRequest(response, incoming, _httpServer, this); | 1872 var request = new _HttpRequest(response, incoming, _httpServer, this); |
| 1875 _streamFuture = outgoing.done | 1873 _streamFuture = outgoing.done |
| 1876 .then((_) { | 1874 .then((_) { |
| 1877 response.deadline = null; | 1875 response.deadline = null; |
| 1878 if (_state == _DETACHED) return; | 1876 if (_state == _DETACHED) return; |
| 1879 if (response.persistentConnection && | 1877 if (response.persistentConnection && |
| 1880 request.persistentConnection && | 1878 request.persistentConnection && |
| 1881 incoming.fullBodyRead) { | 1879 incoming.fullBodyRead && |
| 1880 !_httpParser.upgrade && |
| 1881 !_httpServer.closed) { |
| 1882 _state = _IDLE; | 1882 _state = _IDLE; |
| 1883 _startTimeout(); | 1883 _startTimeout(); |
| 1884 // Resume the subscription for incoming requests as the | 1884 // Resume the subscription for incoming requests as the |
| 1885 // request is now processed. | 1885 // request is now processed. |
| 1886 _subscription.resume(); | 1886 _subscription.resume(); |
| 1887 } else { | 1887 } else { |
| 1888 // Close socket, keep-alive not used or body sent before | 1888 // Close socket, keep-alive not used or body sent before |
| 1889 // received data was handled. | 1889 // received data was handled. |
| 1890 destroy(); | 1890 destroy(); |
| 1891 } | 1891 } |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2000 _connections.add(connection); | 2000 _connections.add(connection); |
| 2001 }, | 2001 }, |
| 2002 onError: _controller.addError, | 2002 onError: _controller.addError, |
| 2003 onDone: _controller.close); | 2003 onDone: _controller.close); |
| 2004 return _controller.stream.listen(onData, | 2004 return _controller.stream.listen(onData, |
| 2005 onError: onError, | 2005 onError: onError, |
| 2006 onDone: onDone, | 2006 onDone: onDone, |
| 2007 cancelOnError: cancelOnError); | 2007 cancelOnError: cancelOnError); |
| 2008 } | 2008 } |
| 2009 | 2009 |
| 2010 Future close() { | 2010 Future close({bool force: false}) { |
| 2011 closed = true; | 2011 closed = true; |
| 2012 Future result; | 2012 Future result; |
| 2013 if (_serverSocket != null && _closeServer) { | 2013 if (_serverSocket != null && _closeServer) { |
| 2014 result = _serverSocket.close(); | 2014 result = _serverSocket.close(); |
| 2015 } else { | 2015 } else { |
| 2016 result = new Future.value(); | 2016 result = new Future.value(); |
| 2017 } | 2017 } |
| 2018 if (_sessionManagerInstance != null) { | 2018 if (force) { |
| 2019 for (var c in _connections.toList()) { |
| 2020 c.destroy(); |
| 2021 } |
| 2022 assert(_connections.isEmpty); |
| 2023 } else { |
| 2024 for (var c in _connections.where((c) => c._isIdle).toList()) { |
| 2025 c.destroy(); |
| 2026 } |
| 2027 } |
| 2028 _maybeCloseSessionManager(); |
| 2029 return result; |
| 2030 } |
| 2031 |
| 2032 void _maybeCloseSessionManager() { |
| 2033 if (closed && |
| 2034 _connections.isEmpty && |
| 2035 _sessionManagerInstance != null) { |
| 2019 _sessionManagerInstance.close(); | 2036 _sessionManagerInstance.close(); |
| 2020 _sessionManagerInstance = null; | 2037 _sessionManagerInstance = null; |
| 2021 } | 2038 } |
| 2022 for (_HttpConnection connection in _connections.toList()) { | |
| 2023 connection.destroy(); | |
| 2024 } | |
| 2025 _connections.clear(); | |
| 2026 return result; | |
| 2027 } | 2039 } |
| 2028 | 2040 |
| 2029 int get port { | 2041 int get port { |
| 2030 if (closed) throw new HttpException("HttpServer is not bound to a socket"); | 2042 if (closed) throw new HttpException("HttpServer is not bound to a socket"); |
| 2031 return _serverSocket.port; | 2043 return _serverSocket.port; |
| 2032 } | 2044 } |
| 2033 | 2045 |
| 2034 InternetAddress get address { | 2046 InternetAddress get address { |
| 2035 if (closed) throw new HttpException("HttpServer is not bound to a socket"); | 2047 if (closed) throw new HttpException("HttpServer is not bound to a socket"); |
| 2036 return _serverSocket.address; | 2048 return _serverSocket.address; |
| 2037 } | 2049 } |
| 2038 | 2050 |
| 2039 set sessionTimeout(int timeout) { | 2051 set sessionTimeout(int timeout) { |
| 2040 _sessionManager.sessionTimeout = timeout; | 2052 _sessionManager.sessionTimeout = timeout; |
| 2041 } | 2053 } |
| 2042 | 2054 |
| 2043 void _handleRequest(HttpRequest request) { | 2055 void _handleRequest(HttpRequest request) { |
| 2044 _controller.add(request); | 2056 _controller.add(request); |
| 2045 } | 2057 } |
| 2046 | 2058 |
| 2047 void _handleError(error) { | 2059 void _handleError(error) { |
| 2048 if (!closed) _controller.addError(error); | 2060 if (!closed) _controller.addError(error); |
| 2049 } | 2061 } |
| 2050 | 2062 |
| 2051 void _connectionClosed(_HttpConnection connection) { | 2063 void _connectionClosed(_HttpConnection connection) { |
| 2052 _connections.remove(connection); | 2064 _connections.remove(connection); |
| 2065 _maybeCloseSessionManager(); |
| 2053 } | 2066 } |
| 2054 | 2067 |
| 2055 _HttpSessionManager get _sessionManager { | 2068 _HttpSessionManager get _sessionManager { |
| 2056 // Lazy init. | 2069 // Lazy init. |
| 2057 if (_sessionManagerInstance == null) { | 2070 if (_sessionManagerInstance == null) { |
| 2058 _sessionManagerInstance = new _HttpSessionManager(); | 2071 _sessionManagerInstance = new _HttpSessionManager(); |
| 2059 } | 2072 } |
| 2060 return _sessionManagerInstance; | 2073 return _sessionManagerInstance; |
| 2061 } | 2074 } |
| 2062 | 2075 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2169 final String username; | 2182 final String username; |
| 2170 final String password; | 2183 final String password; |
| 2171 final bool isDirect; | 2184 final bool isDirect; |
| 2172 } | 2185 } |
| 2173 | 2186 |
| 2174 | 2187 |
| 2175 class _HttpConnectionInfo implements HttpConnectionInfo { | 2188 class _HttpConnectionInfo implements HttpConnectionInfo { |
| 2176 static _HttpConnectionInfo create(Socket socket) { | 2189 static _HttpConnectionInfo create(Socket socket) { |
| 2177 if (socket == null) return null; | 2190 if (socket == null) return null; |
| 2178 try { | 2191 try { |
| 2179 _HttpConnectionInfo info = new _HttpConnectionInfo._(); | 2192 _HttpConnectionInfo info = new _HttpConnectionInfo(); |
| 2180 info.remoteHost = socket.remoteHost; | 2193 info.remoteHost = socket.remoteHost; |
| 2181 info.remotePort = socket.remotePort; | 2194 info.remotePort = socket.remotePort; |
| 2182 info.localPort = socket.port; | 2195 info.localPort = socket.port; |
| 2183 return info; | 2196 return info; |
| 2184 } catch (e) { } | 2197 } catch (e) { } |
| 2185 return null; | 2198 return null; |
| 2186 } | 2199 } |
| 2187 | 2200 |
| 2188 _HttpConnectionInfo._(); | |
| 2189 | |
| 2190 String remoteHost; | 2201 String remoteHost; |
| 2191 int remotePort; | 2202 int remotePort; |
| 2192 int localPort; | 2203 int localPort; |
| 2193 } | 2204 } |
| 2194 | 2205 |
| 2195 | 2206 |
| 2196 class _DetachedSocket extends Stream<List<int>> implements Socket { | 2207 class _DetachedSocket extends Stream<List<int>> implements Socket { |
| 2197 final Stream<List<int>> _incoming; | 2208 final Stream<List<int>> _incoming; |
| 2198 final Socket _socket; | 2209 final Socket _socket; |
| 2199 | 2210 |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2494 final Uri location; | 2505 final Uri location; |
| 2495 } | 2506 } |
| 2496 | 2507 |
| 2497 String _getHttpVersion() { | 2508 String _getHttpVersion() { |
| 2498 var version = Platform.version; | 2509 var version = Platform.version; |
| 2499 // Only include major and minor version numbers. | 2510 // Only include major and minor version numbers. |
| 2500 int index = version.indexOf('.', version.indexOf('.') + 1); | 2511 int index = version.indexOf('.', version.indexOf('.') + 1); |
| 2501 version = version.substring(0, index); | 2512 version = version.substring(0, index); |
| 2502 return 'Dart/$version (dart:io)'; | 2513 return 'Dart/$version (dart:io)'; |
| 2503 } | 2514 } |
| OLD | NEW |