| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |