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

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

Issue 36643002: Don't close existing connection on HttpServer close (and stream cancel). (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix 'disable keep-alive' on server close. Created 7 years, 2 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.dart ('k') | tests/standalone/io/http_client_connect_test.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 520 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « sdk/lib/io/http.dart ('k') | tests/standalone/io/http_client_connect_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698