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

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

Issue 22839013: Add HttpServer.idleTimeout for closing idle keep-alive connections. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 4 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_server_idle_timeout_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 1806 matching lines...) Expand 10 before | Expand all | Expand 10 after
1817 static const _IDLE = 1; 1817 static const _IDLE = 1;
1818 static const _CLOSING = 2; 1818 static const _CLOSING = 2;
1819 static const _DETACHED = 3; 1819 static const _DETACHED = 3;
1820 1820
1821 int _state = _IDLE; 1821 int _state = _IDLE;
1822 1822
1823 final Socket _socket; 1823 final Socket _socket;
1824 final _HttpServer _httpServer; 1824 final _HttpServer _httpServer;
1825 final _HttpParser _httpParser; 1825 final _HttpParser _httpParser;
1826 StreamSubscription _subscription; 1826 StreamSubscription _subscription;
1827 Timer _idleTimer;
1827 1828
1828 Future _streamFuture; 1829 Future _streamFuture;
1829 1830
1830 _HttpConnection(Socket this._socket, _HttpServer this._httpServer) 1831 _HttpConnection(Socket this._socket, _HttpServer this._httpServer)
1831 : _httpParser = new _HttpParser.requestParser() { 1832 : _httpParser = new _HttpParser.requestParser() {
1833 _startTimeout();
1832 _socket.pipe(_httpParser); 1834 _socket.pipe(_httpParser);
1833 _subscription = _httpParser.listen( 1835 _subscription = _httpParser.listen(
1834 (incoming) { 1836 (incoming) {
1837 _stopTimeout();
1835 // If the incoming was closed, close the connection. 1838 // If the incoming was closed, close the connection.
1836 incoming.dataDone.then((closing) { 1839 incoming.dataDone.then((closing) {
1837 if (closing) destroy(); 1840 if (closing) destroy();
1838 }); 1841 });
1839 // Only handle one incoming request at the time. Keep the 1842 // Only handle one incoming request at the time. Keep the
1840 // stream paused until the request has been send. 1843 // stream paused until the request has been send.
1841 _subscription.pause(); 1844 _subscription.pause();
1842 _state = _ACTIVE; 1845 _state = _ACTIVE;
1843 var outgoing = new _HttpOutgoing(_socket); 1846 var outgoing = new _HttpOutgoing(_socket);
1844 var response = new _HttpResponse(incoming.uri, 1847 var response = new _HttpResponse(incoming.uri,
1845 incoming.headers.protocolVersion, 1848 incoming.headers.protocolVersion,
1846 outgoing, 1849 outgoing,
1847 _httpServer.serverHeader); 1850 _httpServer.serverHeader);
1848 var request = new _HttpRequest(response, incoming, _httpServer, this); 1851 var request = new _HttpRequest(response, incoming, _httpServer, this);
1849 _streamFuture = outgoing.done 1852 _streamFuture = outgoing.done
1850 .then((_) { 1853 .then((_) {
1851 response.deadline = null; 1854 response.deadline = null;
1852 if (_state == _DETACHED) return; 1855 if (_state == _DETACHED) return;
1853 if (response.persistentConnection && 1856 if (response.persistentConnection &&
1854 request.persistentConnection && 1857 request.persistentConnection &&
1855 incoming.fullBodyRead) { 1858 incoming.fullBodyRead) {
1856 _state = _IDLE; 1859 _state = _IDLE;
1860 _startTimeout();
1857 // Resume the subscription for incoming requests as the 1861 // Resume the subscription for incoming requests as the
1858 // request is now processed. 1862 // request is now processed.
1859 _subscription.resume(); 1863 _subscription.resume();
1860 } else { 1864 } else {
1861 // Close socket, keep-alive not used or body sent before 1865 // Close socket, keep-alive not used or body sent before
1862 // received data was handled. 1866 // received data was handled.
1863 destroy(); 1867 destroy();
1864 } 1868 }
1865 }) 1869 })
1866 .catchError((e) { 1870 .catchError((e) {
1867 destroy(); 1871 destroy();
1868 }); 1872 });
1869 response._ignoreBody = request.method == "HEAD"; 1873 response._ignoreBody = request.method == "HEAD";
1870 response._httpRequest = request; 1874 response._httpRequest = request;
1871 _httpServer._handleRequest(request); 1875 _httpServer._handleRequest(request);
1872 }, 1876 },
1873 onDone: () { 1877 onDone: () {
1874 destroy(); 1878 destroy();
1875 }, 1879 },
1876 onError: (error) { 1880 onError: (error) {
1877 // Ignore failed requests that was closed before headers was received. 1881 // Ignore failed requests that was closed before headers was received.
1878 destroy(); 1882 destroy();
1879 }); 1883 });
1880 } 1884 }
1881 1885
1886 void _startTimeout() {
1887 assert(_state == _IDLE);
1888 _stopTimeout();
1889 if (_httpServer.idleTimeout == null) return;
1890 _idleTimer = new Timer(_httpServer.idleTimeout, () {
1891 destroy();
1892 });
1893 }
1894
1895 void _stopTimeout() {
1896 if (_idleTimer != null) _idleTimer.cancel();
1897 }
1898
1882 void destroy() { 1899 void destroy() {
1900 _stopTimeout();
1883 if (_state == _CLOSING || _state == _DETACHED) return; 1901 if (_state == _CLOSING || _state == _DETACHED) return;
1884 _state = _CLOSING; 1902 _state = _CLOSING;
1885 _socket.destroy(); 1903 _socket.destroy();
1886 _httpServer._connectionClosed(this); 1904 _httpServer._connectionClosed(this);
1887 } 1905 }
1888 1906
1889 Future<Socket> detachSocket() { 1907 Future<Socket> detachSocket() {
1908 _stopTimeout();
1890 _state = _DETACHED; 1909 _state = _DETACHED;
1891 // Remove connection from server. 1910 // Remove connection from server.
1892 _httpServer._connectionClosed(this); 1911 _httpServer._connectionClosed(this);
1893 1912
1894 _HttpDetachedIncoming detachedIncoming = _httpParser.detachIncoming(); 1913 _HttpDetachedIncoming detachedIncoming = _httpParser.detachIncoming();
1895 1914
1896 return _streamFuture.then((_) { 1915 return _streamFuture.then((_) {
1897 return new _DetachedSocket(_socket, detachedIncoming); 1916 return new _DetachedSocket(_socket, detachedIncoming);
1898 }); 1917 });
1899 } 1918 }
1900 1919
1901 HttpConnectionInfo get connectionInfo => _HttpConnectionInfo.create(_socket); 1920 HttpConnectionInfo get connectionInfo => _HttpConnectionInfo.create(_socket);
1902 1921
1903 bool get _isActive => _state == _ACTIVE; 1922 bool get _isActive => _state == _ACTIVE;
1904 bool get _isIdle => _state == _IDLE; 1923 bool get _isIdle => _state == _IDLE;
1905 bool get _isClosing => _state == _CLOSING; 1924 bool get _isClosing => _state == _CLOSING;
1906 bool get _isDetached => _state == _DETACHED; 1925 bool get _isDetached => _state == _DETACHED;
1907 } 1926 }
1908 1927
1909 1928
1910 // HTTP server waiting for socket connections. 1929 // HTTP server waiting for socket connections.
1911 class _HttpServer extends Stream<HttpRequest> implements HttpServer { 1930 class _HttpServer extends Stream<HttpRequest> implements HttpServer {
1912 String serverHeader = _getHttpVersion(); 1931 String serverHeader = _getHttpVersion();
1913 1932
1933 Duration idleTimeout = const Duration(seconds: 120);
1934
1914 static Future<HttpServer> bind(address, int port, int backlog) { 1935 static Future<HttpServer> bind(address, int port, int backlog) {
1915 return ServerSocket.bind(address, port, backlog: backlog).then((socket) { 1936 return ServerSocket.bind(address, port, backlog: backlog).then((socket) {
1916 return new _HttpServer._(socket, true); 1937 return new _HttpServer._(socket, true);
1917 }); 1938 });
1918 } 1939 }
1919 1940
1920 static Future<HttpServer> bindSecure(address, 1941 static Future<HttpServer> bindSecure(address,
1921 int port, 1942 int port,
1922 int backlog, 1943 int backlog,
1923 String certificate_name, 1944 String certificate_name,
(...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after
2445 final Uri location; 2466 final Uri location;
2446 } 2467 }
2447 2468
2448 String _getHttpVersion() { 2469 String _getHttpVersion() {
2449 var version = Platform.version; 2470 var version = Platform.version;
2450 // Only include major and minor version numbers. 2471 // Only include major and minor version numbers.
2451 int index = version.indexOf('.', version.indexOf('.') + 1); 2472 int index = version.indexOf('.', version.indexOf('.') + 1);
2452 version = version.substring(0, index); 2473 version = version.substring(0, index);
2453 return 'Dart/$version (dart:io)'; 2474 return 'Dart/$version (dart:io)';
2454 } 2475 }
OLDNEW
« no previous file with comments | « sdk/lib/io/http.dart ('k') | tests/standalone/io/http_server_idle_timeout_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698