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 |