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

Side by Side Diff: runtime/bin/http_impl.dart

Issue 11066041: Add support for HTTP proxy in the HTTP client (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Minor fixes Created 8 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
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 828 matching lines...) Expand 10 before | Expand all | Expand 10 after
839 List<String> headerValues = headers["cookie"]; 839 List<String> headerValues = headers["cookie"];
840 if (headerValues != null) { 840 if (headerValues != null) {
841 headerValues.forEach((headerValue) => _parseCookieString(headerValue)); 841 headerValues.forEach((headerValue) => _parseCookieString(headerValue));
842 } 842 }
843 return _cookies; 843 return _cookies;
844 } 844 }
845 845
846 InputStream get inputStream { 846 InputStream get inputStream {
847 if (_inputStream == null) { 847 if (_inputStream == null) {
848 _inputStream = new _HttpInputStream(this); 848 _inputStream = new _HttpInputStream(this);
849 _inputStream._streamMarkedClosed = _dataEndCalled;
849 } 850 }
850 return _inputStream; 851 return _inputStream;
851 } 852 }
852 853
853 String get protocolVersion => _protocolVersion; 854 String get protocolVersion => _protocolVersion;
854 855
855 void _onRequestStart(String method, String uri, String version) { 856 void _onRequestStart(String method, String uri, String version) {
856 _method = method; 857 _method = method;
857 _uri = uri; 858 _uri = uri;
858 _parseRequestUri(uri); 859 _parseRequestUri(uri);
859 } 860 }
860 861
861 void _onHeaderReceived(String name, String value) { 862 void _onHeaderReceived(String name, String value) {
862 _headers.add(name, value); 863 _headers.add(name, value);
863 } 864 }
864 865
865 void _onHeadersComplete() { 866 void _onHeadersComplete() {
866 _headers._mutable = false; 867 _headers._mutable = false;
867 // Prepare for receiving data. 868 // Prepare for receiving data.
868 _buffer = new _BufferList(); 869 _buffer = new _BufferList();
869 } 870 }
870 871
871 void _onDataReceived(List<int> data) { 872 void _onDataReceived(List<int> data) {
872 _buffer.add(data); 873 _buffer.add(data);
873 if (_inputStream != null) _inputStream._dataReceived(); 874 if (_inputStream != null) _inputStream._dataReceived();
874 } 875 }
875 876
876 void _onDataEnd() { 877 void _onDataEnd() {
877 if (_inputStream != null) _inputStream._closeReceived(); 878 if (_inputStream != null) _inputStream._closeReceived();
879 _dataEndCalled = true;
878 } 880 }
879 881
880 // Escaped characters in uri are expected to have been parsed. 882 // Escaped characters in uri are expected to have been parsed.
881 void _parseRequestUri(String uri) { 883 void _parseRequestUri(String uri) {
882 int position; 884 int position;
883 position = uri.indexOf("?", 0); 885 position = uri.indexOf("?", 0);
884 if (position == -1) { 886 if (position == -1) {
885 _path = _HttpUtils.decodeUrlEncodedString(_uri); 887 _path = _HttpUtils.decodeUrlEncodedString(_uri);
886 _queryString = null; 888 _queryString = null;
887 _queryParameters = new Map(); 889 _queryParameters = new Map();
(...skipping 22 matching lines...) Expand all
910 _streamErrorHandler = callback; 912 _streamErrorHandler = callback;
911 } 913 }
912 914
913 String _method; 915 String _method;
914 String _uri; 916 String _uri;
915 String _path; 917 String _path;
916 String _queryString; 918 String _queryString;
917 Map<String, String> _queryParameters; 919 Map<String, String> _queryParameters;
918 _HttpInputStream _inputStream; 920 _HttpInputStream _inputStream;
919 _BufferList _buffer; 921 _BufferList _buffer;
922 bool _dataEndCalled = false;
920 Function _streamErrorHandler; 923 Function _streamErrorHandler;
921 } 924 }
922 925
923 926
924 // HTTP response object for sending a HTTP response. 927 // HTTP response object for sending a HTTP response.
925 class _HttpResponse extends _HttpRequestResponseBase implements HttpResponse { 928 class _HttpResponse extends _HttpRequestResponseBase implements HttpResponse {
926 _HttpResponse(_HttpConnection httpConnection) 929 _HttpResponse(_HttpConnection httpConnection)
927 : super(httpConnection), 930 : super(httpConnection),
928 _statusCode = HttpStatus.OK; 931 _statusCode = HttpStatus.OK;
929 932
(...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after
1537 Set<_HttpConnection> _connections; // Set of currently connected clients. 1540 Set<_HttpConnection> _connections; // Set of currently connected clients.
1538 List<_RequestHandlerRegistration> _handlers; 1541 List<_RequestHandlerRegistration> _handlers;
1539 Object _defaultHandler; 1542 Object _defaultHandler;
1540 Function _onError; 1543 Function _onError;
1541 } 1544 }
1542 1545
1543 1546
1544 class _HttpClientRequest 1547 class _HttpClientRequest
1545 extends _HttpRequestResponseBase implements HttpClientRequest { 1548 extends _HttpRequestResponseBase implements HttpClientRequest {
1546 _HttpClientRequest(String this._method, 1549 _HttpClientRequest(String this._method,
1547 String this._uri, 1550 Uri this._uri,
1548 _HttpClientConnection connection) 1551 _HttpClientConnection connection)
1549 : super(connection) { 1552 : super(connection) {
1550 _connection = connection; 1553 _connection = connection;
1551 // Default GET and HEAD requests to have no content. 1554 // Default GET and HEAD requests to have no content.
1552 if (_method == "GET" || _method == "HEAD") { 1555 if (_method == "GET" || _method == "HEAD") {
1553 _contentLength = 0; 1556 _contentLength = 0;
1554 } 1557 }
1555 } 1558 }
1556 1559
1557 void set contentLength(int contentLength) { 1560 void set contentLength(int contentLength) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1606 _streamErrorHandler = callback; 1609 _streamErrorHandler = callback;
1607 } 1610 }
1608 1611
1609 void _writeHeader() { 1612 void _writeHeader() {
1610 List<int> data; 1613 List<int> data;
1611 1614
1612 // Write request line. 1615 // Write request line.
1613 data = _method.toString().charCodes(); 1616 data = _method.toString().charCodes();
1614 _httpConnection._write(data); 1617 _httpConnection._write(data);
1615 _writeSP(); 1618 _writeSP();
1616 data = _uri.toString().charCodes(); 1619 // Send the path for direct connections and the whole URL for
1620 // proxy connections.
1621 if (!_connection._usingProxy) {
1622 String path;
1623 if (_uri.query != "") {
1624 if (_uri.fragment != "") {
1625 path = "${_uri.path}?${_uri.query}#${_uri.fragment}";
1626 } else {
1627 path = "${_uri.path}?${_uri.query}";
1628 }
1629 } else {
1630 path = _uri.path;
1631 }
1632 data = path.charCodes();
1633 } else {
1634 data = _uri.toString().charCodes();
1635 }
1617 _httpConnection._write(data); 1636 _httpConnection._write(data);
1618 _writeSP(); 1637 _writeSP();
1619 _httpConnection._write(_Const.HTTP11); 1638 _httpConnection._write(_Const.HTTP11);
1620 _writeCRLF(); 1639 _writeCRLF();
1621 1640
1622 // Determine the value of the "Transfer-Encoding" header based on 1641 // Determine the value of the "Transfer-Encoding" header based on
1623 // whether the content length is known. If there is no content 1642 // whether the content length is known. If there is no content
1624 // neither "Content-Length" nor "Transfer-Encoding" is set 1643 // neither "Content-Length" nor "Transfer-Encoding" is set
1625 if (_contentLength > 0) { 1644 if (_contentLength > 0) {
1626 _headers.set(HttpHeaders.CONTENT_LENGTH, _contentLength.toString()); 1645 _headers.set(HttpHeaders.CONTENT_LENGTH, _contentLength.toString());
(...skipping 12 matching lines...) Expand all
1639 } 1658 }
1640 _headers.add("cookie", sb.toString()); 1659 _headers.add("cookie", sb.toString());
1641 } 1660 }
1642 1661
1643 // Write headers. 1662 // Write headers.
1644 _writeHeaders(); 1663 _writeHeaders();
1645 _state = HEADER_SENT; 1664 _state = HEADER_SENT;
1646 } 1665 }
1647 1666
1648 String _method; 1667 String _method;
1649 String _uri; 1668 Uri _uri;
1650 _HttpClientConnection _connection; 1669 _HttpClientConnection _connection;
1651 _HttpOutputStream _outputStream; 1670 _HttpOutputStream _outputStream;
1652 Function _streamErrorHandler; 1671 Function _streamErrorHandler;
1653 } 1672 }
1654 1673
1655 1674
1656 class _HttpClientResponse 1675 class _HttpClientResponse
1657 extends _HttpRequestResponseBase implements HttpClientResponse { 1676 extends _HttpRequestResponseBase implements HttpClientResponse {
1658 _HttpClientResponse(_HttpClientConnection connection) 1677 _HttpClientResponse(_HttpClientConnection connection)
1659 : super(connection) { 1678 : super(connection) {
(...skipping 18 matching lines...) Expand all
1678 values.forEach((value) { 1697 values.forEach((value) {
1679 _cookies.add(new Cookie.fromSetCookieValue(value)); 1698 _cookies.add(new Cookie.fromSetCookieValue(value));
1680 }); 1699 });
1681 } 1700 }
1682 return _cookies; 1701 return _cookies;
1683 } 1702 }
1684 1703
1685 InputStream get inputStream { 1704 InputStream get inputStream {
1686 if (_inputStream == null) { 1705 if (_inputStream == null) {
1687 _inputStream = new _HttpInputStream(this); 1706 _inputStream = new _HttpInputStream(this);
1707 _inputStream._streamMarkedClosed = _dataEndCalled;
1688 } 1708 }
1689 return _inputStream; 1709 return _inputStream;
1690 } 1710 }
1691 1711
1692 void _onRequestStart(String method, String uri, String version) { 1712 void _onRequestStart(String method, String uri, String version) {
1693 // TODO(sgjesse): Error handling 1713 // TODO(sgjesse): Error handling
1694 } 1714 }
1695 1715
1696 void _onResponseStart(int statusCode, String reasonPhrase, String version) { 1716 void _onResponseStart(int statusCode, String reasonPhrase, String version) {
1697 _statusCode = statusCode; 1717 _statusCode = statusCode;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1739 } 1759 }
1740 1760
1741 void _onDataReceived(List<int> data) { 1761 void _onDataReceived(List<int> data) {
1742 _buffer.add(data); 1762 _buffer.add(data);
1743 if (_inputStream != null) _inputStream._dataReceived(); 1763 if (_inputStream != null) _inputStream._dataReceived();
1744 } 1764 }
1745 1765
1746 void _onDataEnd() { 1766 void _onDataEnd() {
1747 _connection._responseDone(); 1767 _connection._responseDone();
1748 if (_inputStream != null) _inputStream._closeReceived(); 1768 if (_inputStream != null) _inputStream._closeReceived();
1769 _dataEndCalled = true;
1749 } 1770 }
1750 1771
1751 // Delegate functions for the HttpInputStream implementation. 1772 // Delegate functions for the HttpInputStream implementation.
1752 int _streamAvailable() { 1773 int _streamAvailable() {
1753 return _buffer.length; 1774 return _buffer.length;
1754 } 1775 }
1755 1776
1756 List<int> _streamRead(int bytesToRead) { 1777 List<int> _streamRead(int bytesToRead) {
1757 return _buffer.readBytes(bytesToRead); 1778 return _buffer.readBytes(bytesToRead);
1758 } 1779 }
1759 1780
1760 int _streamReadInto(List<int> buffer, int offset, int len) { 1781 int _streamReadInto(List<int> buffer, int offset, int len) {
1761 List<int> data = _buffer.readBytes(len); 1782 List<int> data = _buffer.readBytes(len);
1762 buffer.setRange(offset, data.length, data); 1783 buffer.setRange(offset, data.length, data);
1763 return data.length; 1784 return data.length;
1764 } 1785 }
1765 1786
1766 void _streamSetErrorHandler(callback(e)) { 1787 void _streamSetErrorHandler(callback(e)) {
1767 _streamErrorHandler = callback; 1788 _streamErrorHandler = callback;
1768 } 1789 }
1769 1790
1770 int _statusCode; 1791 int _statusCode;
1771 String _reasonPhrase; 1792 String _reasonPhrase;
1772 1793
1773 _HttpClientConnection _connection; 1794 _HttpClientConnection _connection;
1774 _HttpInputStream _inputStream; 1795 _HttpInputStream _inputStream;
1775 _BufferList _buffer; 1796 _BufferList _buffer;
1797 bool _dataEndCalled = false;
1798
1776 Function _streamErrorHandler; 1799 Function _streamErrorHandler;
1777 } 1800 }
1778 1801
1779 1802
1780 class _HttpClientConnection 1803 class _HttpClientConnection
1781 extends _HttpConnectionBase implements HttpClientConnection { 1804 extends _HttpConnectionBase implements HttpClientConnection {
1782 _HttpClientConnection(_HttpClient this._client); 1805 _HttpClientConnection(_HttpClient this._client);
1783 1806
1784 void _connectionEstablished(_SocketConnection socketConn) { 1807 void _connectionEstablished(_SocketConnection socketConn) {
1785 super._connectionEstablished(socketConn._socket); 1808 super._connectionEstablished(socketConn._socket);
(...skipping 17 matching lines...) Expand all
1803 if (_socket != null) { 1826 if (_socket != null) {
1804 _socket.close(); 1827 _socket.close();
1805 } 1828 }
1806 } else { 1829 } else {
1807 _client._returnSocketConnection(_socketConn); 1830 _client._returnSocketConnection(_socketConn);
1808 } 1831 }
1809 _socket = null; 1832 _socket = null;
1810 _socketConn = null; 1833 _socketConn = null;
1811 } 1834 }
1812 1835
1813 HttpClientRequest open(String method, String uri) { 1836 HttpClientRequest open(String method, Uri uri) {
1814 _method = method; 1837 _method = method;
1815 // Tell the HTTP parser the method it is expecting a response to. 1838 // Tell the HTTP parser the method it is expecting a response to.
1816 _httpParser.responseToMethod = method; 1839 _httpParser.responseToMethod = method;
1817 _request = new _HttpClientRequest(method, uri, this); 1840 _request = new _HttpClientRequest(method, uri, this);
1818 _response = new _HttpClientResponse(this); 1841 _response = new _HttpClientResponse(this);
1819 return _request; 1842 return _request;
1820 } 1843 }
1821 1844
1822 DetachedSocket detachSocket() { 1845 DetachedSocket detachSocket() {
1823 return _detachSocket(); 1846 return _detachSocket();
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1906 1929
1907 Function _onRequest; 1930 Function _onRequest;
1908 Function _onResponse; 1931 Function _onResponse;
1909 Function _onErrorCallback; 1932 Function _onErrorCallback;
1910 1933
1911 _HttpClient _client; 1934 _HttpClient _client;
1912 _SocketConnection _socketConn; 1935 _SocketConnection _socketConn;
1913 HttpClientRequest _request; 1936 HttpClientRequest _request;
1914 HttpClientResponse _response; 1937 HttpClientResponse _response;
1915 String _method; 1938 String _method;
1939 bool _usingProxy;
1916 1940
1917 // Redirect handling 1941 // Redirect handling
1918 bool followRedirects = true; 1942 bool followRedirects = true;
1919 int maxRedirects = 5; 1943 int maxRedirects = 5;
1920 List<_RedirectInfo> _redirects; 1944 List<_RedirectInfo> _redirects;
1921 1945
1922 // Callbacks. 1946 // Callbacks.
1923 var requestReceived; 1947 var requestReceived;
1924 } 1948 }
1925 1949
(...skipping 15 matching lines...) Expand all
1941 Duration _idleTime(Date now) => now.difference(_returnTime); 1965 Duration _idleTime(Date now) => now.difference(_returnTime);
1942 1966
1943 int hashCode() => _socket.hashCode(); 1967 int hashCode() => _socket.hashCode();
1944 1968
1945 String _host; 1969 String _host;
1946 int _port; 1970 int _port;
1947 Socket _socket; 1971 Socket _socket;
1948 Date _returnTime; 1972 Date _returnTime;
1949 } 1973 }
1950 1974
1975 class _ProxyConfiguration {
1976 static const String PROXY_PREFIX = "PROXY ";
1977 static const String DIRECT_PREFIX = "DIRECT";
1978
1979 _ProxyConfiguration(String configuration) : proxies = new List<_Proxy>() {
1980 if (configuration == null) {
1981 throw new HttpException("Invalid proxy configuration $configuration");
1982 }
1983 List<String> list = configuration.split(";");
1984 list.forEach((String proxy) {
1985 proxy = proxy.trim();
1986 if (!proxy.isEmpty()) {
1987 if (proxy.startsWith(PROXY_PREFIX)) {
1988 int colon = proxy.indexOf(":");
1989 if (colon == -1 || colon == 0 || colon == proxy.length - 1) {
1990 throw new HttpException(
1991 "Invalid proxy configuration $configuration");
1992 }
1993 // Skip the "PROXY " prefix.
1994 String host = proxy.substring(PROXY_PREFIX.length, colon).trim();
1995 int port = int.parse(proxy.substring(colon + 1).trim());
Anders Johnsen 2012/10/08 11:05:25 Try around parse (or the hole method)?
Søren Gjesse 2012/10/08 12:17:30 Done.
1996 proxies.add(new _Proxy(host, port));
1997 } else if (proxy.trim() == DIRECT_PREFIX) {
1998 proxies.add(new _Proxy.direct());
1999 } else {
2000 throw new HttpException("Invalid proxy configuration $configuration");
2001 }
2002 }
2003 });
2004 }
2005 const _ProxyConfiguration.direct()
2006 : proxies = [const _Proxy.direct()];
2007
2008 final List<_Proxy> proxies;
2009 }
2010
2011 class _Proxy {
2012 const _Proxy(this.host, this.port) : direct = false;
2013 const _Proxy.direct() : host = null, port = null, direct = true;
2014
2015 final String host;
2016 final int port;
2017 final bool direct;
2018 }
1951 2019
1952 class _HttpClient implements HttpClient { 2020 class _HttpClient implements HttpClient {
1953 static const int DEFAULT_EVICTION_TIMEOUT = 60000; 2021 static const int DEFAULT_EVICTION_TIMEOUT = 60000;
1954 2022
1955 _HttpClient() : _openSockets = new Map(), 2023 _HttpClient() : _openSockets = new Map(),
1956 _activeSockets = new Set(), 2024 _activeSockets = new Set(),
1957 _shutdown = false; 2025 _shutdown = false;
1958 2026
1959 HttpClientConnection open( 2027 HttpClientConnection open(
1960 String method, String host, int port, String path) { 2028 String method, String host, int port, String path) {
1961 // TODO(sgjesse): The path set here can contain both query and 2029 // TODO(sgjesse): The path set here can contain both query and
1962 // fragment. They should be cracked and set correctly. 2030 // fragment. They should be cracked and set correctly.
1963 return _open(method, new Uri.fromComponents( 2031 return _open(method, new Uri.fromComponents(
1964 scheme: "http", domain: host, port: port, path: path)); 2032 scheme: "http", domain: host, port: port, path: path));
1965 } 2033 }
1966 2034
1967 HttpClientConnection _open(String method, 2035 HttpClientConnection _open(String method,
1968 Uri uri, 2036 Uri uri,
1969 [_HttpClientConnection connection]) { 2037 [_HttpClientConnection connection]) {
1970 if (_shutdown) throw new HttpException("HttpClient shutdown"); 2038 if (_shutdown) throw new HttpException("HttpClient shutdown");
1971 if (method == null || uri.domain.isEmpty() == null) { 2039 if (method == null || uri.domain.isEmpty() == null) {
1972 throw new ArgumentError(null); 2040 throw new ArgumentError(null);
1973 } 2041 }
1974 return _prepareHttpClientConnection(method, uri, connection); 2042 return _prepareHttpClientConnection(method, uri, connection);
1975 } 2043 }
1976 2044
1977 HttpClientConnection openUrl(String method, Uri url) { 2045 HttpClientConnection openUrl(String method, Uri url) {
1978 _openUrl(method, url); 2046 return _openUrl(method, url);
Anders Johnsen 2012/10/08 11:05:25 Nice catch :)
1979 } 2047 }
1980 2048
1981 HttpClientConnection _openUrl(String method, 2049 HttpClientConnection _openUrl(String method,
1982 Uri url, 2050 Uri url,
1983 [_HttpClientConnection connection]) { 2051 [_HttpClientConnection connection]) {
1984 if (url.scheme != "http") { 2052 if (url.scheme != "http") {
1985 throw new HttpException("Unsupported URL scheme ${url.scheme}"); 2053 throw new HttpException("Unsupported URL scheme ${url.scheme}");
1986 } 2054 }
1987 if (url.userInfo != "") { 2055 if (url.userInfo != "") {
1988 throw new HttpException("Unsupported user info ${url.userInfo}"); 2056 throw new HttpException("Unsupported user info ${url.userInfo}");
1989 } 2057 }
1990 return _open(method, url, connection); 2058 return _open(method, url, connection);
1991 } 2059 }
1992 2060
1993 HttpClientConnection get(String host, int port, String path) { 2061 HttpClientConnection get(String host, int port, String path) {
1994 return open("GET", host, port, path); 2062 return open("GET", host, port, path);
1995 } 2063 }
1996 2064
1997 HttpClientConnection getUrl(Uri url) => _openUrl("GET", url); 2065 HttpClientConnection getUrl(Uri url) => _openUrl("GET", url);
1998 2066
1999 HttpClientConnection post(String host, int port, String path) { 2067 HttpClientConnection post(String host, int port, String path) {
2000 return open("POST", host, port, path); 2068 return open("POST", host, port, path);
2001 } 2069 }
2002 2070
2003 HttpClientConnection postUrl(Uri url) => _openUrl("POST", url); 2071 HttpClientConnection postUrl(Uri url) => _openUrl("POST", url);
2004 2072
2073 set findProxy(String f(Uri uri)) => _findProxy = f;
2074
2005 void shutdown() { 2075 void shutdown() {
2006 _openSockets.forEach((String key, Queue<_SocketConnection> connections) { 2076 _openSockets.forEach((String key, Queue<_SocketConnection> connections) {
2007 while (!connections.isEmpty()) { 2077 while (!connections.isEmpty()) {
2008 _SocketConnection socketConn = connections.removeFirst(); 2078 _SocketConnection socketConn = connections.removeFirst();
2009 socketConn._socket.close(); 2079 socketConn._socket.close();
2010 } 2080 }
2011 }); 2081 });
2012 _activeSockets.forEach((_SocketConnection socketConn) { 2082 _activeSockets.forEach((_SocketConnection socketConn) {
2013 socketConn._socket.close(); 2083 socketConn._socket.close();
2014 }); 2084 });
(...skipping 12 matching lines...) Expand all
2027 2097
2028 HttpClientConnection _prepareHttpClientConnection( 2098 HttpClientConnection _prepareHttpClientConnection(
2029 String method, 2099 String method,
2030 Uri url, 2100 Uri url,
2031 [_HttpClientConnection connection]) { 2101 [_HttpClientConnection connection]) {
2032 2102
2033 String host = url.domain; 2103 String host = url.domain;
2034 int port = url.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : url.port; 2104 int port = url.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : url.port;
2035 2105
2036 void _connectionOpened(_SocketConnection socketConn, 2106 void _connectionOpened(_SocketConnection socketConn,
2037 _HttpClientConnection connection) { 2107 _HttpClientConnection connection,
2108 bool usingProxy) {
2109 connection._usingProxy = usingProxy;
2038 connection._connectionEstablished(socketConn); 2110 connection._connectionEstablished(socketConn);
2039 String path; 2111 HttpClientRequest request = connection.open(method, url);
2040 if (url.query != "") {
2041 if (url.fragment != "") {
2042 path = "${url.path}?${url.query}#${url.fragment}";
2043 } else {
2044 path = "${url.path}?${url.query}";
2045 }
2046 } else {
2047 path = url.path;
2048 }
2049 HttpClientRequest request = connection.open(method, path);
2050 request.headers.host = host; 2112 request.headers.host = host;
2051 request.headers.port = port; 2113 request.headers.port = port;
2052 if (connection._onRequest != null) { 2114 if (connection._onRequest != null) {
2053 connection._onRequest(request); 2115 connection._onRequest(request);
2054 } else { 2116 } else {
2055 request.outputStream.close(); 2117 request.outputStream.close();
2056 } 2118 }
2057 } 2119 }
2058 2120
2059 // Create a new connection if we are not re-using an existing one. 2121 // Create a new connection if we are not re-using an existing one.
2060 if (connection == null) { 2122 if (connection == null) {
2061 connection = new _HttpClientConnection(this); 2123 connection = new _HttpClientConnection(this);
2062 } 2124 }
2063 connection.onDetach = () => _activeSockets.remove(connection._socketConn); 2125 connection.onDetach = () => _activeSockets.remove(connection._socketConn);
2064 2126
2127 // Check to see if a proxy server should be used for this connection.
2128 _ProxyConfiguration proxyConfiguration = const _ProxyConfiguration.direct();
2129 if (_findProxy != null) {
2130 // TODO(sgjesse): Keep a map of these as normally only a few
Anders Johnsen 2012/10/08 11:05:25 That's only valid if it won't change over time. Is
Søren Gjesse 2012/10/08 12:17:30 In most cases only a few different strings will be
Anders Johnsen 2012/10/08 12:27:29 Ahh okay!
2131 // configuration strings will be used.
2132 proxyConfiguration = new _ProxyConfiguration(_findProxy(url));
2133 }
2134
2135 // Determine the actual host to connect to.
2136 String connectHost;
2137 int connectPort;
2138 if (proxyConfiguration.proxies[0].direct) {
Anders Johnsen 2012/10/08 11:05:25 proxyConfiguration.proxies[0] is used quite a bit.
Søren Gjesse 2012/10/08 12:17:30 Done.
2139 connectHost = host;
2140 connectPort = port;
2141 } else {
2142 connectHost = proxyConfiguration.proxies[0].host;
2143 connectPort = proxyConfiguration.proxies[0].port;
2144 }
2145
2065 // If there are active connections for this key get the first one 2146 // If there are active connections for this key get the first one
2066 // otherwise create a new one. 2147 // otherwise create a new one.
2067 String key = _connectionKey(host, port); 2148 String key = _connectionKey(connectHost, connectPort);
2068 Queue socketConnections = _openSockets[key]; 2149 Queue socketConnections = _openSockets[key];
2069 if (socketConnections == null || socketConnections.isEmpty()) { 2150 if (socketConnections == null || socketConnections.isEmpty()) {
2070 Socket socket = new Socket(host, port); 2151 Socket socket = new Socket(connectHost, connectPort);
2071 // Until the connection is established handle connection errors 2152 // Until the connection is established handle connection errors
2072 // here as the HttpClientConnection object is not yet associated 2153 // here as the HttpClientConnection object is not yet associated
2073 // with the socket. 2154 // with the socket.
2074 socket.onError = (e) { 2155 socket.onError = (e) {
2075 // Report the error through the HttpClientConnection object to 2156 // Report the error through the HttpClientConnection object to
2076 // the client. 2157 // the client.
2077 connection._onError(e); 2158 connection._onError(e);
2078 }; 2159 };
2079 socket.onConnect = () { 2160 socket.onConnect = () {
2080 // When the connection is established, clear the error 2161 // When the connection is established, clear the error
2081 // callback as it will now be handled by the 2162 // callback as it will now be handled by the
2082 // HttpClientConnection object which will be associated with 2163 // HttpClientConnection object which will be associated with
2083 // the connected socket. 2164 // the connected socket.
2084 socket.onError = null; 2165 socket.onError = null;
2085 _SocketConnection socketConn = 2166 _SocketConnection socketConn =
2086 new _SocketConnection(host, port, socket); 2167 new _SocketConnection(connectHost, connectPort, socket);
2087 _activeSockets.add(socketConn); 2168 _activeSockets.add(socketConn);
2088 _connectionOpened(socketConn, connection); 2169 _connectionOpened(socketConn,
2170 connection,
2171 !proxyConfiguration.proxies[0].direct);
2089 }; 2172 };
2090 } else { 2173 } else {
2091 _SocketConnection socketConn = socketConnections.removeFirst(); 2174 _SocketConnection socketConn = socketConnections.removeFirst();
2092 _activeSockets.add(socketConn); 2175 _activeSockets.add(socketConn);
2093 new Timer(0, (ignored) => _connectionOpened(socketConn, connection)); 2176 new Timer(0, (ignored) =>
2177 _connectionOpened(socketConn,
2178 connection,
2179 !proxyConfiguration.proxies[0].direct));
2094 2180
2095 // Get rid of eviction timer if there are no more active connections. 2181 // Get rid of eviction timer if there are no more active connections.
2096 if (socketConnections.isEmpty()) _openSockets.remove(key); 2182 if (socketConnections.isEmpty()) _openSockets.remove(key);
2097 if (_openSockets.isEmpty()) _cancelEvictionTimer(); 2183 if (_openSockets.isEmpty()) _cancelEvictionTimer();
2098 } 2184 }
2099 2185
2100 return connection; 2186 return connection;
2101 } 2187 }
2102 2188
2103 void _returnSocketConnection(_SocketConnection socketConn) { 2189 void _returnSocketConnection(_SocketConnection socketConn) {
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
2181 2267
2182 2268
2183 class _RedirectInfo implements RedirectInfo { 2269 class _RedirectInfo implements RedirectInfo {
2184 const _RedirectInfo(int this.statusCode, 2270 const _RedirectInfo(int this.statusCode,
2185 String this.method, 2271 String this.method,
2186 Uri this.location); 2272 Uri this.location);
2187 final int statusCode; 2273 final int statusCode;
2188 final String method; 2274 final String method;
2189 final Uri location; 2275 final Uri location;
2190 } 2276 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698