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

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

Issue 11364134: Merge libv1. (Closed) Base URL: https://dart.googlecode.com/svn/experimental/lib_v2/dart
Patch Set: Reupload due to error 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 | « sdk/lib/io/directory_impl.dart ('k') | sdk/lib/io/http_parser.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 1289 matching lines...) Expand 10 before | Expand all | Expand 10 after
1300 1300
1301 void _onData() { 1301 void _onData() {
1302 int available = _socket.available(); 1302 int available = _socket.available();
1303 if (available == 0) { 1303 if (available == 0) {
1304 return; 1304 return;
1305 } 1305 }
1306 1306
1307 List<int> buffer = new Uint8List(available); 1307 List<int> buffer = new Uint8List(available);
1308 int bytesRead = _socket.readList(buffer, 0, available); 1308 int bytesRead = _socket.readList(buffer, 0, available);
1309 if (bytesRead > 0) { 1309 if (bytesRead > 0) {
1310 int parsed = _httpParser.writeList(buffer, 0, bytesRead); 1310 _httpParser.writeList(buffer, 0, bytesRead);
1311 if (!_httpParser.upgrade) {
1312 if (parsed != bytesRead) {
1313 if (_socket != null) {
1314 // TODO(sgjesse): Error handling.
1315 _destroy();
1316 }
1317 }
1318 }
1319 } 1311 }
1320 } 1312 }
1321 1313
1322 void _onClosed() { 1314 void _onClosed() {
1323 _closing = true; 1315 _closing = true;
1324 _onConnectionClosed(null); 1316 _onConnectionClosed(null);
1325 } 1317 }
1326 1318
1327 void _onError(e) { 1319 void _onError(e) {
1328 // If an error occurs, make sure to close the socket if one is associated. 1320 // If an error occurs, make sure to close the socket if one is associated.
1329 _error = true; 1321 _error = true;
1330 if (_socket != null) { 1322 if (_socket != null) {
1331 _socket.close(); 1323 _socket.close();
1332 } 1324 }
1333 _onConnectionClosed(e); 1325 _onConnectionClosed(e);
1334 } 1326 }
1335 1327
1336 DetachedSocket _detachSocket() { 1328 DetachedSocket _detachSocket() {
1337 _socket.onData = null; 1329 _socket.onData = null;
1338 _socket.onClosed = null; 1330 _socket.onClosed = null;
1339 _socket.onError = null; 1331 _socket.onError = null;
1340 _socket.outputStream.onNoPendingWrites = null; 1332 _socket.outputStream.onNoPendingWrites = null;
1341 Socket socket = _socket; 1333 Socket socket = _socket;
1342 _socket = null; 1334 _socket = null;
1343 if (onDetach != null) onDetach(); 1335 if (onDetach != null) onDetach();
1344 return new _DetachedSocket(socket, _httpParser.unparsedData); 1336 return new _DetachedSocket(socket, _httpParser.readUnparsedData());
1345 } 1337 }
1346 1338
1347 HttpConnectionInfo get connectionInfo { 1339 HttpConnectionInfo get connectionInfo {
1348 if (_socket == null || _closing || _error) return null; 1340 if (_socket == null || _closing || _error) return null;
1349 try { 1341 try {
1350 _HttpConnectionInfo info = new _HttpConnectionInfo(); 1342 _HttpConnectionInfo info = new _HttpConnectionInfo();
1351 info.remoteHost = _socket.remoteHost; 1343 info.remoteHost = _socket.remoteHost;
1352 info.remotePort = _socket.remotePort; 1344 info.remotePort = _socket.remotePort;
1353 info.localPort = _socket.port; 1345 info.localPort = _socket.port;
1354 return info; 1346 return info;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1392 _httpParser.headersComplete = () => _onHeadersComplete(); 1384 _httpParser.headersComplete = () => _onHeadersComplete();
1393 _httpParser.dataReceived = (data) => _onDataReceived(data); 1385 _httpParser.dataReceived = (data) => _onDataReceived(data);
1394 _httpParser.dataEnd = (close) => _onDataEnd(close); 1386 _httpParser.dataEnd = (close) => _onDataEnd(close);
1395 _httpParser.error = (e) => _onError(e); 1387 _httpParser.error = (e) => _onError(e);
1396 } 1388 }
1397 1389
1398 void _onConnectionClosed(e) { 1390 void _onConnectionClosed(e) {
1399 // Don't report errors when HTTP parser is in idle state. Clients 1391 // Don't report errors when HTTP parser is in idle state. Clients
1400 // can close the connection and cause a connection reset by peer 1392 // can close the connection and cause a connection reset by peer
1401 // error which is OK. 1393 // error which is OK.
1402 if (e != null && onError != null && !_httpParser.isIdle) { 1394 if (e != null && !_httpParser.isIdle) {
1403 onError(e); 1395 onError(e);
1404 // Propagate the error to the streams. 1396 // Propagate the error to the streams.
1405 if (_request != null && _request._streamErrorHandler != null) { 1397 if (_request != null && _request._streamErrorHandler != null) {
1406 _request._streamErrorHandler(e); 1398 _request._streamErrorHandler(e);
1407 } 1399 }
1408 if (_response != null && _response._streamErrorHandler != null) { 1400 if (_response != null && _response._streamErrorHandler != null) {
1409 _response._streamErrorHandler(e); 1401 _response._streamErrorHandler(e);
1410 } 1402 }
1411 } 1403 }
1412 1404
1413 // If currently not processing any request close the socket when 1405 // If currently not processing any request close the socket when
1414 // we are done writing the response. 1406 // we are done writing the response.
1415 if (_httpParser.isIdle) { 1407 if (_httpParser.isIdle) {
1416 _socket.outputStream.onClosed = () { 1408 // If the httpParser is idle and we get an error from the
1417 _destroy(); 1409 // connection we deal with that as a closed connection and not
1418 if (onClosed != null && e == null) { 1410 // as an error. When the client disappears we get a connection
1419 // Don't call onClosed if onError has been called. 1411 // reset by peer and that is OK.
1412 if (e != null) {
1413 onClosed();
1414 } else {
1415 _socket.outputStream.onClosed = () {
1416 _destroy();
1420 onClosed(); 1417 onClosed();
1421 } 1418 };
1422 }; 1419 // If the client closes and we are done writing the response
1423 // If the client closes and we are done writing the response 1420 // the connection should be closed.
1424 // the connection should be closed. 1421 if (_response == null) _close();
1425 if (_response == null) _close(); 1422 }
1426 return; 1423 } else {
1427 } 1424 // Processing a request.
1428 1425 if (e == null) {
1429 // Processing a request. 1426 // Indicate connection close to the HTTP parser.
1430 if (e == null) { 1427 _httpParser.connectionClosed();
1431 // Indicate connection close to the HTTP parser. 1428 }
1432 _httpParser.connectionClosed();
1433 } 1429 }
1434 } 1430 }
1435 1431
1436 void _onRequestStart(String method, String uri, String version) { 1432 void _onRequestStart(String method, String uri, String version) {
1437 // Create new request and response objects for this request. 1433 // Create new request and response objects for this request.
1438 _request = new _HttpRequest(this); 1434 _request = new _HttpRequest(this);
1439 _response = new _HttpResponse(this); 1435 _response = new _HttpResponse(this);
1440 _request._onRequestStart(method, uri, version); 1436 _request._onRequestStart(method, uri, version);
1441 _request._protocolVersion = version; 1437 _request._protocolVersion = version;
1442 _response._protocolVersion = version; 1438 _response._protocolVersion = version;
(...skipping 23 matching lines...) Expand all
1466 void _onDataEnd(bool close) { 1462 void _onDataEnd(bool close) {
1467 _request._onDataEnd(); 1463 _request._onDataEnd();
1468 } 1464 }
1469 1465
1470 void _responseDone() { 1466 void _responseDone() {
1471 // If the connection is closing then close the output stream to 1467 // If the connection is closing then close the output stream to
1472 // fully close the socket. 1468 // fully close the socket.
1473 if (_closing) { 1469 if (_closing) {
1474 _socket.outputStream.onClosed = () { 1470 _socket.outputStream.onClosed = () {
1475 _socket.close(); 1471 _socket.close();
1472 onClosed();
1476 }; 1473 };
1477 } 1474 }
1478 _response = null; 1475 _response = null;
1479 } 1476 }
1480 1477
1481 HttpServer _server; 1478 HttpServer _server;
1482 HttpRequest _request; 1479 HttpRequest _request;
1483 HttpResponse _response; 1480 HttpResponse _response;
1484 1481
1485 // Callbacks. 1482 // Callbacks.
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
1660 _httpConnection._flush(); 1657 _httpConnection._flush();
1661 } 1658 }
1662 1659
1663 void _streamClose() { 1660 void _streamClose() {
1664 _ensureHeadersSent(); 1661 _ensureHeadersSent();
1665 _state = DONE; 1662 _state = DONE;
1666 // Stop tracking no pending write events. 1663 // Stop tracking no pending write events.
1667 _httpConnection._onNoPendingWrites = null; 1664 _httpConnection._onNoPendingWrites = null;
1668 // Ensure that any trailing data is written. 1665 // Ensure that any trailing data is written.
1669 _writeDone(); 1666 _writeDone();
1667 _connection._requestDone();
1670 } 1668 }
1671 1669
1672 void _streamSetNoPendingWriteHandler(callback()) { 1670 void _streamSetNoPendingWriteHandler(callback()) {
1673 if (_state != DONE) { 1671 if (_state != DONE) {
1674 _httpConnection._onNoPendingWrites = callback; 1672 _httpConnection._onNoPendingWrites = callback;
1675 } 1673 }
1676 } 1674 }
1677 1675
1678 void _streamSetCloseHandler(callback()) { 1676 void _streamSetCloseHandler(callback()) {
1679 // TODO(sgjesse): Handle this. 1677 // TODO(sgjesse): Handle this.
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
1796 } 1794 }
1797 1795
1798 void _handleUnauthorized() { 1796 void _handleUnauthorized() {
1799 1797
1800 void retryRequest(_Credentials cr) { 1798 void retryRequest(_Credentials cr) {
1801 if (cr != null) { 1799 if (cr != null) {
1802 // Drain body and retry. 1800 // Drain body and retry.
1803 // TODO(sgjesse): Support digest. 1801 // TODO(sgjesse): Support digest.
1804 if (cr.scheme == _AuthenticationScheme.BASIC) { 1802 if (cr.scheme == _AuthenticationScheme.BASIC) {
1805 inputStream.onData = inputStream.read; 1803 inputStream.onData = inputStream.read;
1806 inputStream.onClosed = _connection.retry; 1804 _connection._retry();
1807 return; 1805 return;
1808 } 1806 }
1809 } 1807 }
1810 1808
1811 // Fall through to here to perform normal response handling if 1809 // Fall through to here to perform normal response handling if
1812 // there is no sensible authorization handling. 1810 // there is no sensible authorization handling.
1813 if (_connection._onResponse != null) { 1811 if (_connection._onResponse != null) {
1814 _connection._onResponse(this); 1812 _connection._onResponse(this);
1815 } 1813 }
1816 } 1814 }
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1890 Uri redirectUrl = new Uri.fromString(location[0]); 1888 Uri redirectUrl = new Uri.fromString(location[0]);
1891 for (int i = 0; i < _connection._redirects.length; i++) { 1889 for (int i = 0; i < _connection._redirects.length; i++) {
1892 if (_connection._redirects[i].location.toString() == 1890 if (_connection._redirects[i].location.toString() ==
1893 redirectUrl.toString()) { 1891 redirectUrl.toString()) {
1894 throw new RedirectLoopException(_connection._redirects); 1892 throw new RedirectLoopException(_connection._redirects);
1895 } 1893 }
1896 } 1894 }
1897 } 1895 }
1898 // Drain body and redirect. 1896 // Drain body and redirect.
1899 inputStream.onData = inputStream.read; 1897 inputStream.onData = inputStream.read;
1900 inputStream.onClosed = _connection.redirect; 1898 _connection.redirect();
1901 } else { 1899 } else {
1902 throw new RedirectLimitExceededException(_connection._redirects); 1900 throw new RedirectLimitExceededException(_connection._redirects);
1903 } 1901 }
1904 } else if (statusCode == HttpStatus.UNAUTHORIZED) { 1902 } else if (statusCode == HttpStatus.UNAUTHORIZED) {
1905 _handleUnauthorized(); 1903 _handleUnauthorized();
1906 } else if (_connection._onResponse != null) { 1904 } else if (_connection._onResponse != null) {
1907 _connection._onResponse(this); 1905 _connection._onResponse(this);
1908 } 1906 }
1909 } 1907 }
1910 1908
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1945 _HttpInputStream _inputStream; 1943 _HttpInputStream _inputStream;
1946 _BufferList _buffer; 1944 _BufferList _buffer;
1947 bool _dataEndCalled = false; 1945 bool _dataEndCalled = false;
1948 1946
1949 Function _streamErrorHandler; 1947 Function _streamErrorHandler;
1950 } 1948 }
1951 1949
1952 1950
1953 class _HttpClientConnection 1951 class _HttpClientConnection
1954 extends _HttpConnectionBase implements HttpClientConnection { 1952 extends _HttpConnectionBase implements HttpClientConnection {
1953 static const int NONE = 0;
1954 static const int REQUEST_DONE = 1;
1955 static const int RESPONSE_DONE = 2;
1956 static const int ALL_DONE = REQUEST_DONE | RESPONSE_DONE;
1957
1955 _HttpClientConnection(_HttpClient this._client); 1958 _HttpClientConnection(_HttpClient this._client);
1956 1959
1957 void _connectionEstablished(_SocketConnection socketConn) { 1960 void _connectionEstablished(_SocketConnection socketConn) {
1958 super._connectionEstablished(socketConn._socket); 1961 super._connectionEstablished(socketConn._socket);
1959 _socketConn = socketConn; 1962 _socketConn = socketConn;
1960 // Register HTTP parser callbacks. 1963 // Register HTTP parser callbacks.
1961 _httpParser.requestStart = 1964 _httpParser.requestStart =
1962 (method, uri, version) => _onRequestStart(method, uri, version); 1965 (method, uri, version) => _onRequestStart(method, uri, version);
1963 _httpParser.responseStart = 1966 _httpParser.responseStart =
1964 (statusCode, reasonPhrase, version) => 1967 (statusCode, reasonPhrase, version) =>
1965 _onResponseStart(statusCode, reasonPhrase, version); 1968 _onResponseStart(statusCode, reasonPhrase, version);
1966 _httpParser.headerReceived = 1969 _httpParser.headerReceived =
1967 (name, value) => _onHeaderReceived(name, value); 1970 (name, value) => _onHeaderReceived(name, value);
1968 _httpParser.headersComplete = () => _onHeadersComplete(); 1971 _httpParser.headersComplete = () => _onHeadersComplete();
1969 _httpParser.dataReceived = (data) => _onDataReceived(data); 1972 _httpParser.dataReceived = (data) => _onDataReceived(data);
1970 _httpParser.dataEnd = (closed) => _onDataEnd(closed); 1973 _httpParser.dataEnd = (closed) => _onDataEnd(closed);
1971 _httpParser.error = (e) => _onError(e); 1974 _httpParser.error = (e) => _onError(e);
1972 } 1975 }
1973 1976
1977 bool get _isRequestDone => (_state & REQUEST_DONE) == REQUEST_DONE;
1978 bool get _isResponseDone => (_state & RESPONSE_DONE) == RESPONSE_DONE;
1979 bool get _isAllDone => (_state & ALL_DONE) == ALL_DONE;
1980
1981 void _checkSocketDone() {
1982 if (_isAllDone) {
1983 if (!_closing) {
1984 _client._returnSocketConnection(_socketConn);
1985 }
1986 _socket = null;
1987 _socketConn = null;
1988 assert(_pendingRedirect == null || _pendingRetry == null);
1989 if (_pendingRedirect != null) {
1990 _doRedirect(_pendingRedirect);
1991 _pendingRedirect = null;
1992 } else if (_pendingRetry != null) {
1993 _doRetry(_pendingRetry);
1994 _pendingRetry = null;
1995 }
1996 }
1997 }
1998
1999 void _requestDone() {
2000 _state |= REQUEST_DONE;
2001 _checkSocketDone();
2002 }
2003
1974 void _responseDone() { 2004 void _responseDone() {
1975 if (_closing) { 2005 if (_closing) {
1976 if (_socket != null) { 2006 if (_socket != null) {
1977 _socket.close(); 2007 _socket.close();
1978 } 2008 }
1979 } else {
1980 _client._returnSocketConnection(_socketConn);
1981 } 2009 }
1982 _socket = null; 2010 _state |= RESPONSE_DONE;
1983 _socketConn = null; 2011 _checkSocketDone();
1984 } 2012 }
1985 2013
1986 HttpClientRequest open(String method, Uri uri) { 2014 HttpClientRequest open(String method, Uri uri) {
1987 _method = method; 2015 _method = method;
1988 // Tell the HTTP parser the method it is expecting a response to. 2016 // Tell the HTTP parser the method it is expecting a response to.
1989 _httpParser.responseToMethod = method; 2017 _httpParser.responseToMethod = method;
1990 _request = new _HttpClientRequest(method, uri, this); 2018 _request = new _HttpClientRequest(method, uri, this);
1991 _response = new _HttpClientResponse(this); 2019 _response = new _HttpClientResponse(this);
1992 return _request; 2020 return _request;
1993 } 2021 }
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
2050 } 2078 }
2051 2079
2052 void set onResponse(void handler(HttpClientResponse response)) { 2080 void set onResponse(void handler(HttpClientResponse response)) {
2053 _onResponse = handler; 2081 _onResponse = handler;
2054 } 2082 }
2055 2083
2056 void set onError(void callback(e)) { 2084 void set onError(void callback(e)) {
2057 _onErrorCallback = callback; 2085 _onErrorCallback = callback;
2058 } 2086 }
2059 2087
2060 void retry() { 2088 void _doRetry(_RedirectInfo retry) {
2061 if (_socketConn != null) { 2089 assert(_socketConn == null);
2062 throw new HttpException("Cannot retry with body data pending"); 2090 _request = null;
2091 _response = null;
2092
2093 // Retry the URL using the same connection instance.
2094 _state = NONE;
2095 _client._openUrl(retry.method, retry.location, this);
2096 }
2097
2098 void _retry() {
2099 var retry = new _RedirectInfo(_response.statusCode, _method, _request._uri);
2100 // The actual retry is postponed until both response and request
2101 // are done.
2102 if (_isAllDone) {
2103 _doRetry(retry);
2104 } else {
2105 // Prepare for retry.
2106 assert(_pendingRedirect == null);
2107 _pendingRetry = retry;
2063 } 2108 }
2064 // Retry the URL using the same connection instance. 2109 }
2065 _client._openUrl(_method, _request._uri, this); 2110
2111 void _doRedirect(_RedirectInfo redirect) {
2112 assert(_socketConn == null);
2113
2114 if (_redirects == null) {
2115 _redirects = new List<_RedirectInfo>();
2116 }
2117 _redirects.add(redirect);
2118 _doRetry(redirect);
2066 } 2119 }
2067 2120
2068 void redirect([String method, Uri url]) { 2121 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; 2122 if (method == null) method = _method;
2073 if (url == null) { 2123 if (url == null) {
2074 url = new Uri.fromString(_response.headers.value(HttpHeaders.LOCATION)); 2124 url = new Uri.fromString(_response.headers.value(HttpHeaders.LOCATION));
2075 } 2125 }
2076 if (_redirects == null) { 2126 var redirect = new _RedirectInfo(_response.statusCode, method, url);
2077 _redirects = new List<_RedirectInfo>(); 2127 // The actual redirect is postponed until both response and
2128 // request are done.
2129 if (_isAllDone) {
2130 _doRedirect(redirect);
2131 } else {
2132 // Prepare for redirect.
2133 assert(_pendingRetry == null);
2134 _pendingRedirect = redirect;
2078 } 2135 }
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 } 2136 }
2085 2137
2138 int _state = NONE;
2139
2086 List<RedirectInfo> get redirects => _redirects; 2140 List<RedirectInfo> get redirects => _redirects;
2087 2141
2088 Function _onRequest; 2142 Function _onRequest;
2089 Function _onResponse; 2143 Function _onResponse;
2090 Function _onErrorCallback; 2144 Function _onErrorCallback;
2091 2145
2092 _HttpClient _client; 2146 _HttpClient _client;
2093 _SocketConnection _socketConn; 2147 _SocketConnection _socketConn;
2094 HttpClientRequest _request; 2148 HttpClientRequest _request;
2095 HttpClientResponse _response; 2149 HttpClientResponse _response;
2096 String _method; 2150 String _method;
2097 bool _usingProxy; 2151 bool _usingProxy;
2098 2152
2099 // Redirect handling 2153 // Redirect handling
2100 bool followRedirects = true; 2154 bool followRedirects = true;
2101 int maxRedirects = 5; 2155 int maxRedirects = 5;
2102 List<_RedirectInfo> _redirects; 2156 List<_RedirectInfo> _redirects;
2157 _RedirectInfo _pendingRedirect;
2158 _RedirectInfo _pendingRetry;
2103 2159
2104 // Callbacks. 2160 // Callbacks.
2105 var requestReceived; 2161 var requestReceived;
2106 } 2162 }
2107 2163
2108 2164
2109 // Class for holding keep-alive sockets in the cache for the HTTP 2165 // Class for holding keep-alive sockets in the cache for the HTTP
2110 // client together with the connection information. 2166 // client together with the connection information.
2111 class _SocketConnection { 2167 class _SocketConnection {
2112 _SocketConnection(String this._host, 2168 _SocketConnection(String this._host,
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after
2596 2652
2597 2653
2598 class _RedirectInfo implements RedirectInfo { 2654 class _RedirectInfo implements RedirectInfo {
2599 const _RedirectInfo(int this.statusCode, 2655 const _RedirectInfo(int this.statusCode,
2600 String this.method, 2656 String this.method,
2601 Uri this.location); 2657 Uri this.location);
2602 final int statusCode; 2658 final int statusCode;
2603 final String method; 2659 final String method;
2604 final Uri location; 2660 final Uri location;
2605 } 2661 }
OLDNEW
« no previous file with comments | « sdk/lib/io/directory_impl.dart ('k') | sdk/lib/io/http_parser.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698