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

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

Issue 11361119: Keep track of the request and response state in the HTTP client connection (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed review comments Created 8 years, 1 month 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 | « pkg/pkg.status ('k') | tests/standalone/io/regress-6521.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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 class _HttpHeaders implements HttpHeaders { 5 class _HttpHeaders implements HttpHeaders {
6 _HttpHeaders() : _headers = new Map<String, List<String>>(); 6 _HttpHeaders() : _headers = new Map<String, List<String>>();
7 7
8 List<String> operator[](String name) { 8 List<String> operator[](String name) {
9 name = name.toLowerCase(); 9 name = name.toLowerCase();
10 return _headers[name]; 10 return _headers[name];
(...skipping 1649 matching lines...) Expand 10 before | Expand all | Expand 10 after
1660 _httpConnection._flush(); 1660 _httpConnection._flush();
1661 } 1661 }
1662 1662
1663 void _streamClose() { 1663 void _streamClose() {
1664 _ensureHeadersSent(); 1664 _ensureHeadersSent();
1665 _state = DONE; 1665 _state = DONE;
1666 // Stop tracking no pending write events. 1666 // Stop tracking no pending write events.
1667 _httpConnection._onNoPendingWrites = null; 1667 _httpConnection._onNoPendingWrites = null;
1668 // Ensure that any trailing data is written. 1668 // Ensure that any trailing data is written.
1669 _writeDone(); 1669 _writeDone();
1670 _connection._requestDone();
1670 } 1671 }
1671 1672
1672 void _streamSetNoPendingWriteHandler(callback()) { 1673 void _streamSetNoPendingWriteHandler(callback()) {
1673 if (_state != DONE) { 1674 if (_state != DONE) {
1674 _httpConnection._onNoPendingWrites = callback; 1675 _httpConnection._onNoPendingWrites = callback;
1675 } 1676 }
1676 } 1677 }
1677 1678
1678 void _streamSetCloseHandler(callback()) { 1679 void _streamSetCloseHandler(callback()) {
1679 // TODO(sgjesse): Handle this. 1680 // TODO(sgjesse): Handle this.
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
1796 } 1797 }
1797 1798
1798 void _handleUnauthorized() { 1799 void _handleUnauthorized() {
1799 1800
1800 void retryRequest(_Credentials cr) { 1801 void retryRequest(_Credentials cr) {
1801 if (cr != null) { 1802 if (cr != null) {
1802 // Drain body and retry. 1803 // Drain body and retry.
1803 // TODO(sgjesse): Support digest. 1804 // TODO(sgjesse): Support digest.
1804 if (cr.scheme == _AuthenticationScheme.BASIC) { 1805 if (cr.scheme == _AuthenticationScheme.BASIC) {
1805 inputStream.onData = inputStream.read; 1806 inputStream.onData = inputStream.read;
1806 inputStream.onClosed = _connection.retry; 1807 _connection._retry();
1807 return; 1808 return;
1808 } 1809 }
1809 } 1810 }
1810 1811
1811 // Fall through to here to perform normal response handling if 1812 // Fall through to here to perform normal response handling if
1812 // there is no sensible authorization handling. 1813 // there is no sensible authorization handling.
1813 if (_connection._onResponse != null) { 1814 if (_connection._onResponse != null) {
1814 _connection._onResponse(this); 1815 _connection._onResponse(this);
1815 } 1816 }
1816 } 1817 }
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1890 Uri redirectUrl = new Uri.fromString(location[0]); 1891 Uri redirectUrl = new Uri.fromString(location[0]);
1891 for (int i = 0; i < _connection._redirects.length; i++) { 1892 for (int i = 0; i < _connection._redirects.length; i++) {
1892 if (_connection._redirects[i].location.toString() == 1893 if (_connection._redirects[i].location.toString() ==
1893 redirectUrl.toString()) { 1894 redirectUrl.toString()) {
1894 throw new RedirectLoopException(_connection._redirects); 1895 throw new RedirectLoopException(_connection._redirects);
1895 } 1896 }
1896 } 1897 }
1897 } 1898 }
1898 // Drain body and redirect. 1899 // Drain body and redirect.
1899 inputStream.onData = inputStream.read; 1900 inputStream.onData = inputStream.read;
1900 inputStream.onClosed = _connection.redirect; 1901 _connection.redirect();
1901 } else { 1902 } else {
1902 throw new RedirectLimitExceededException(_connection._redirects); 1903 throw new RedirectLimitExceededException(_connection._redirects);
1903 } 1904 }
1904 } else if (statusCode == HttpStatus.UNAUTHORIZED) { 1905 } else if (statusCode == HttpStatus.UNAUTHORIZED) {
1905 _handleUnauthorized(); 1906 _handleUnauthorized();
1906 } else if (_connection._onResponse != null) { 1907 } else if (_connection._onResponse != null) {
1907 _connection._onResponse(this); 1908 _connection._onResponse(this);
1908 } 1909 }
1909 } 1910 }
1910 1911
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1945 _HttpInputStream _inputStream; 1946 _HttpInputStream _inputStream;
1946 _BufferList _buffer; 1947 _BufferList _buffer;
1947 bool _dataEndCalled = false; 1948 bool _dataEndCalled = false;
1948 1949
1949 Function _streamErrorHandler; 1950 Function _streamErrorHandler;
1950 } 1951 }
1951 1952
1952 1953
1953 class _HttpClientConnection 1954 class _HttpClientConnection
1954 extends _HttpConnectionBase implements HttpClientConnection { 1955 extends _HttpConnectionBase implements HttpClientConnection {
1956 static const int NONE = 0;
1957 static const int REQUEST_DONE = 1;
1958 static const int RESPONSE_DONE = 2;
1959 static const int ALL_DONE = REQUEST_DONE | RESPONSE_DONE;
1960
1955 _HttpClientConnection(_HttpClient this._client); 1961 _HttpClientConnection(_HttpClient this._client);
1956 1962
1957 void _connectionEstablished(_SocketConnection socketConn) { 1963 void _connectionEstablished(_SocketConnection socketConn) {
1958 super._connectionEstablished(socketConn._socket); 1964 super._connectionEstablished(socketConn._socket);
1959 _socketConn = socketConn; 1965 _socketConn = socketConn;
1960 // Register HTTP parser callbacks. 1966 // Register HTTP parser callbacks.
1961 _httpParser.requestStart = 1967 _httpParser.requestStart =
1962 (method, uri, version) => _onRequestStart(method, uri, version); 1968 (method, uri, version) => _onRequestStart(method, uri, version);
1963 _httpParser.responseStart = 1969 _httpParser.responseStart =
1964 (statusCode, reasonPhrase, version) => 1970 (statusCode, reasonPhrase, version) =>
1965 _onResponseStart(statusCode, reasonPhrase, version); 1971 _onResponseStart(statusCode, reasonPhrase, version);
1966 _httpParser.headerReceived = 1972 _httpParser.headerReceived =
1967 (name, value) => _onHeaderReceived(name, value); 1973 (name, value) => _onHeaderReceived(name, value);
1968 _httpParser.headersComplete = () => _onHeadersComplete(); 1974 _httpParser.headersComplete = () => _onHeadersComplete();
1969 _httpParser.dataReceived = (data) => _onDataReceived(data); 1975 _httpParser.dataReceived = (data) => _onDataReceived(data);
1970 _httpParser.dataEnd = (closed) => _onDataEnd(closed); 1976 _httpParser.dataEnd = (closed) => _onDataEnd(closed);
1971 _httpParser.error = (e) => _onError(e); 1977 _httpParser.error = (e) => _onError(e);
1972 } 1978 }
1973 1979
1980 bool get _isRequestDone => (_state & REQUEST_DONE) == REQUEST_DONE;
1981 bool get _isResponseDone => (_state & RESPONSE_DONE) == RESPONSE_DONE;
1982 bool get _isAllDone => (_state & ALL_DONE) == ALL_DONE;
1983
1984 void _checkSocketDone() {
1985 if (_isAllDone) {
1986 if (!_closing) {
1987 _client._returnSocketConnection(_socketConn);
1988 }
1989 _socket = null;
1990 _socketConn = null;
1991 assert(_pendingRedirect == null || _pendingRetry == null);
1992 if (_pendingRedirect != null) {
1993 _doRedirect(_pendingRedirect);
1994 _pendingRedirect = null;
1995 } else if (_pendingRetry != null) {
1996 _doRetry(_pendingRetry);
1997 _pendingRetry = null;
1998 }
1999 }
2000 }
2001
2002 void _requestDone() {
2003 _state |= REQUEST_DONE;
2004 _checkSocketDone();
2005 }
2006
1974 void _responseDone() { 2007 void _responseDone() {
1975 if (_closing) { 2008 if (_closing) {
1976 if (_socket != null) { 2009 if (_socket != null) {
1977 _socket.close(); 2010 _socket.close();
1978 } 2011 }
1979 } else {
1980 _client._returnSocketConnection(_socketConn);
1981 } 2012 }
1982 _socket = null; 2013 _state |= RESPONSE_DONE;
1983 _socketConn = null; 2014 _checkSocketDone();
1984 } 2015 }
1985 2016
1986 HttpClientRequest open(String method, Uri uri) { 2017 HttpClientRequest open(String method, Uri uri) {
1987 _method = method; 2018 _method = method;
1988 // Tell the HTTP parser the method it is expecting a response to. 2019 // Tell the HTTP parser the method it is expecting a response to.
1989 _httpParser.responseToMethod = method; 2020 _httpParser.responseToMethod = method;
1990 _request = new _HttpClientRequest(method, uri, this); 2021 _request = new _HttpClientRequest(method, uri, this);
1991 _response = new _HttpClientResponse(this); 2022 _response = new _HttpClientResponse(this);
1992 return _request; 2023 return _request;
1993 } 2024 }
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
2050 } 2081 }
2051 2082
2052 void set onResponse(void handler(HttpClientResponse response)) { 2083 void set onResponse(void handler(HttpClientResponse response)) {
2053 _onResponse = handler; 2084 _onResponse = handler;
2054 } 2085 }
2055 2086
2056 void set onError(void callback(e)) { 2087 void set onError(void callback(e)) {
2057 _onErrorCallback = callback; 2088 _onErrorCallback = callback;
2058 } 2089 }
2059 2090
2060 void retry() { 2091 void _doRetry(_RedirectInfo retry) {
2061 if (_socketConn != null) { 2092 assert(_socketConn == null);
2062 throw new HttpException("Cannot retry with body data pending"); 2093 _request = null;
2094 _response = null;
2095
2096 // Retry the URL using the same connection instance.
2097 _state = NONE;
2098 _client._openUrl(retry.method, retry.location, this);
2099 }
2100
2101 void _retry() {
2102 var retry = new _RedirectInfo(_response.statusCode, _method, _request._uri);
2103 // The actual retry is postponed until both response and request
2104 // are done.
2105 if (_isAllDone) {
2106 _doRetry(retry);
2107 } else {
2108 // Prepare for retry.
2109 assert(_pendingRedirect == null);
2110 _pendingRetry = retry;
2063 } 2111 }
2064 // Retry the URL using the same connection instance. 2112 }
2065 _client._openUrl(_method, _request._uri, this); 2113
2114 void _doRedirect(_RedirectInfo redirect) {
2115 assert(_socketConn == null);
2116
2117 if (_redirects == null) {
2118 _redirects = new List<_RedirectInfo>();
2119 }
2120 _redirects.add(redirect);
2121 _doRetry(redirect);
2066 } 2122 }
2067 2123
2068 void redirect([String method, Uri url]) { 2124 void redirect([String method, Uri url]) {
2069 if (_socketConn != null) {
2070 throw new HttpException("Cannot redirect with body data pending");
2071 }
2072 if (method == null) method = _method; 2125 if (method == null) method = _method;
2073 if (url == null) { 2126 if (url == null) {
2074 url = new Uri.fromString(_response.headers.value(HttpHeaders.LOCATION)); 2127 url = new Uri.fromString(_response.headers.value(HttpHeaders.LOCATION));
2075 } 2128 }
2076 if (_redirects == null) { 2129 var redirect = new _RedirectInfo(_response.statusCode, method, url);
2077 _redirects = new List<_RedirectInfo>(); 2130 // The actual redirect is postponed until both response and
2131 // request are done.
2132 if (_isAllDone) {
2133 _doRedirect(redirect);
2134 } else {
2135 // Prepare for redirect.
2136 assert(_pendingRetry == null);
2137 _pendingRedirect = redirect;
2078 } 2138 }
2079 _redirects.add(new _RedirectInfo(_response.statusCode, method, url));
2080 _request = null;
2081 _response = null;
2082 // Open redirect URL using the same connection instance.
2083 _client._openUrl(method, url, this);
2084 } 2139 }
2085 2140
2141 int _state = NONE;
2142
2086 List<RedirectInfo> get redirects => _redirects; 2143 List<RedirectInfo> get redirects => _redirects;
2087 2144
2088 Function _onRequest; 2145 Function _onRequest;
2089 Function _onResponse; 2146 Function _onResponse;
2090 Function _onErrorCallback; 2147 Function _onErrorCallback;
2091 2148
2092 _HttpClient _client; 2149 _HttpClient _client;
2093 _SocketConnection _socketConn; 2150 _SocketConnection _socketConn;
2094 HttpClientRequest _request; 2151 HttpClientRequest _request;
2095 HttpClientResponse _response; 2152 HttpClientResponse _response;
2096 String _method; 2153 String _method;
2097 bool _usingProxy; 2154 bool _usingProxy;
2098 2155
2099 // Redirect handling 2156 // Redirect handling
2100 bool followRedirects = true; 2157 bool followRedirects = true;
2101 int maxRedirects = 5; 2158 int maxRedirects = 5;
2102 List<_RedirectInfo> _redirects; 2159 List<_RedirectInfo> _redirects;
2160 _RedirectInfo _pendingRedirect;
2161 _RedirectInfo _pendingRetry;
2103 2162
2104 // Callbacks. 2163 // Callbacks.
2105 var requestReceived; 2164 var requestReceived;
2106 } 2165 }
2107 2166
2108 2167
2109 // Class for holding keep-alive sockets in the cache for the HTTP 2168 // Class for holding keep-alive sockets in the cache for the HTTP
2110 // client together with the connection information. 2169 // client together with the connection information.
2111 class _SocketConnection { 2170 class _SocketConnection {
2112 _SocketConnection(String this._host, 2171 _SocketConnection(String this._host,
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after
2596 2655
2597 2656
2598 class _RedirectInfo implements RedirectInfo { 2657 class _RedirectInfo implements RedirectInfo {
2599 const _RedirectInfo(int this.statusCode, 2658 const _RedirectInfo(int this.statusCode,
2600 String this.method, 2659 String this.method,
2601 Uri this.location); 2660 Uri this.location);
2602 final int statusCode; 2661 final int statusCode;
2603 final String method; 2662 final String method;
2604 final Uri location; 2663 final Uri location;
2605 } 2664 }
OLDNEW
« no previous file with comments | « pkg/pkg.status ('k') | tests/standalone/io/regress-6521.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698