 Chromium Code Reviews
 Chromium Code Reviews Issue 11066041:
  Add support for HTTP proxy in the HTTP client  (Closed) 
  Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
    
  
    Issue 11066041:
  Add support for HTTP proxy in the HTTP client  (Closed) 
  Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart| 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 828 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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>() { | |
| 
Mads Ager (google)
2012/10/08 16:59:39
Funky indentation.
 
Søren Gjesse
2012/10/09 14:05:22
Done.
 | |
| 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 String portString = proxy.substring(colon + 1).trim(); | |
| 1996 int port; | |
| 1997 try { | |
| 1998 port = int.parse(portString); | |
| 1999 } on FormatException catch (e) { | |
| 2000 throw new HttpException( | |
| 2001 "Invalid proxy configuration $configuration, " | |
| 2002 "invalid port '$portString'"); | |
| 2003 } | |
| 2004 proxies.add(new _Proxy(host, port)); | |
| 2005 } else if (proxy.trim() == DIRECT_PREFIX) { | |
| 2006 proxies.add(new _Proxy.direct()); | |
| 2007 } else { | |
| 2008 throw new HttpException("Invalid proxy configuration $configuration"); | |
| 2009 } | |
| 2010 } | |
| 2011 }); | |
| 2012 } | |
| 2013 const _ProxyConfiguration.direct() | |
| 
Mads Ager (google)
2012/10/08 16:59:39
Maybe add a space between the constructors.
 
Søren Gjesse
2012/10/09 14:05:22
Done.
 | |
| 2014 : proxies = [const _Proxy.direct()]; | |
| 2015 | |
| 2016 final List<_Proxy> proxies; | |
| 2017 } | |
| 2018 | |
| 2019 class _Proxy { | |
| 2020 const _Proxy(this.host, this.port) : direct = false; | |
| 2021 const _Proxy.direct() : host = null, port = null, direct = true; | |
| 2022 | |
| 2023 final String host; | |
| 2024 final int port; | |
| 2025 final bool direct; | |
| 2026 } | |
| 1951 | 2027 | 
| 1952 class _HttpClient implements HttpClient { | 2028 class _HttpClient implements HttpClient { | 
| 1953 static const int DEFAULT_EVICTION_TIMEOUT = 60000; | 2029 static const int DEFAULT_EVICTION_TIMEOUT = 60000; | 
| 1954 | 2030 | 
| 1955 _HttpClient() : _openSockets = new Map(), | 2031 _HttpClient() : _openSockets = new Map(), | 
| 1956 _activeSockets = new Set(), | 2032 _activeSockets = new Set(), | 
| 1957 _shutdown = false; | 2033 _shutdown = false; | 
| 1958 | 2034 | 
| 1959 HttpClientConnection open( | 2035 HttpClientConnection open( | 
| 1960 String method, String host, int port, String path) { | 2036 String method, String host, int port, String path) { | 
| 1961 // TODO(sgjesse): The path set here can contain both query and | 2037 // TODO(sgjesse): The path set here can contain both query and | 
| 1962 // fragment. They should be cracked and set correctly. | 2038 // fragment. They should be cracked and set correctly. | 
| 1963 return _open(method, new Uri.fromComponents( | 2039 return _open(method, new Uri.fromComponents( | 
| 1964 scheme: "http", domain: host, port: port, path: path)); | 2040 scheme: "http", domain: host, port: port, path: path)); | 
| 1965 } | 2041 } | 
| 1966 | 2042 | 
| 1967 HttpClientConnection _open(String method, | 2043 HttpClientConnection _open(String method, | 
| 1968 Uri uri, | 2044 Uri uri, | 
| 1969 [_HttpClientConnection connection]) { | 2045 [_HttpClientConnection connection]) { | 
| 1970 if (_shutdown) throw new HttpException("HttpClient shutdown"); | 2046 if (_shutdown) throw new HttpException("HttpClient shutdown"); | 
| 1971 if (method == null || uri.domain.isEmpty() == null) { | 2047 if (method == null || uri.domain.isEmpty() == null) { | 
| 1972 throw new ArgumentError(null); | 2048 throw new ArgumentError(null); | 
| 1973 } | 2049 } | 
| 1974 return _prepareHttpClientConnection(method, uri, connection); | 2050 return _prepareHttpClientConnection(method, uri, connection); | 
| 1975 } | 2051 } | 
| 1976 | 2052 | 
| 1977 HttpClientConnection openUrl(String method, Uri url) { | 2053 HttpClientConnection openUrl(String method, Uri url) { | 
| 1978 _openUrl(method, url); | 2054 return _openUrl(method, url); | 
| 1979 } | 2055 } | 
| 1980 | 2056 | 
| 1981 HttpClientConnection _openUrl(String method, | 2057 HttpClientConnection _openUrl(String method, | 
| 1982 Uri url, | 2058 Uri url, | 
| 1983 [_HttpClientConnection connection]) { | 2059 [_HttpClientConnection connection]) { | 
| 1984 if (url.scheme != "http") { | 2060 if (url.scheme != "http") { | 
| 1985 throw new HttpException("Unsupported URL scheme ${url.scheme}"); | 2061 throw new HttpException("Unsupported URL scheme ${url.scheme}"); | 
| 1986 } | 2062 } | 
| 1987 if (url.userInfo != "") { | 2063 if (url.userInfo != "") { | 
| 1988 throw new HttpException("Unsupported user info ${url.userInfo}"); | 2064 throw new HttpException("Unsupported user info ${url.userInfo}"); | 
| 1989 } | 2065 } | 
| 1990 return _open(method, url, connection); | 2066 return _open(method, url, connection); | 
| 1991 } | 2067 } | 
| 1992 | 2068 | 
| 1993 HttpClientConnection get(String host, int port, String path) { | 2069 HttpClientConnection get(String host, int port, String path) { | 
| 1994 return open("GET", host, port, path); | 2070 return open("GET", host, port, path); | 
| 1995 } | 2071 } | 
| 1996 | 2072 | 
| 1997 HttpClientConnection getUrl(Uri url) => _openUrl("GET", url); | 2073 HttpClientConnection getUrl(Uri url) => _openUrl("GET", url); | 
| 1998 | 2074 | 
| 1999 HttpClientConnection post(String host, int port, String path) { | 2075 HttpClientConnection post(String host, int port, String path) { | 
| 2000 return open("POST", host, port, path); | 2076 return open("POST", host, port, path); | 
| 2001 } | 2077 } | 
| 2002 | 2078 | 
| 2003 HttpClientConnection postUrl(Uri url) => _openUrl("POST", url); | 2079 HttpClientConnection postUrl(Uri url) => _openUrl("POST", url); | 
| 2004 | 2080 | 
| 2081 set findProxy(String f(Uri uri)) => _findProxy = f; | |
| 2082 | |
| 2005 void shutdown() { | 2083 void shutdown() { | 
| 2006 _openSockets.forEach((String key, Queue<_SocketConnection> connections) { | 2084 _openSockets.forEach((String key, Queue<_SocketConnection> connections) { | 
| 2007 while (!connections.isEmpty()) { | 2085 while (!connections.isEmpty()) { | 
| 2008 _SocketConnection socketConn = connections.removeFirst(); | 2086 _SocketConnection socketConn = connections.removeFirst(); | 
| 2009 socketConn._socket.close(); | 2087 socketConn._socket.close(); | 
| 2010 } | 2088 } | 
| 2011 }); | 2089 }); | 
| 2012 _activeSockets.forEach((_SocketConnection socketConn) { | 2090 _activeSockets.forEach((_SocketConnection socketConn) { | 
| 2013 socketConn._socket.close(); | 2091 socketConn._socket.close(); | 
| 2014 }); | 2092 }); | 
| (...skipping 12 matching lines...) Expand all Loading... | |
| 2027 | 2105 | 
| 2028 HttpClientConnection _prepareHttpClientConnection( | 2106 HttpClientConnection _prepareHttpClientConnection( | 
| 2029 String method, | 2107 String method, | 
| 2030 Uri url, | 2108 Uri url, | 
| 2031 [_HttpClientConnection connection]) { | 2109 [_HttpClientConnection connection]) { | 
| 2032 | 2110 | 
| 2033 String host = url.domain; | 2111 String host = url.domain; | 
| 2034 int port = url.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : url.port; | 2112 int port = url.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : url.port; | 
| 2035 | 2113 | 
| 2036 void _connectionOpened(_SocketConnection socketConn, | 2114 void _connectionOpened(_SocketConnection socketConn, | 
| 2037 _HttpClientConnection connection) { | 2115 _HttpClientConnection connection, | 
| 2116 bool usingProxy) { | |
| 2117 connection._usingProxy = usingProxy; | |
| 2038 connection._connectionEstablished(socketConn); | 2118 connection._connectionEstablished(socketConn); | 
| 2039 String path; | 2119 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; | 2120 request.headers.host = host; | 
| 2051 request.headers.port = port; | 2121 request.headers.port = port; | 
| 2052 if (connection._onRequest != null) { | 2122 if (connection._onRequest != null) { | 
| 2053 connection._onRequest(request); | 2123 connection._onRequest(request); | 
| 2054 } else { | 2124 } else { | 
| 2055 request.outputStream.close(); | 2125 request.outputStream.close(); | 
| 2056 } | 2126 } | 
| 2057 } | 2127 } | 
| 2058 | 2128 | 
| 2059 // Create a new connection if we are not re-using an existing one. | 2129 // Create a new connection if we are not re-using an existing one. | 
| 2060 if (connection == null) { | 2130 if (connection == null) { | 
| 2061 connection = new _HttpClientConnection(this); | 2131 connection = new _HttpClientConnection(this); | 
| 2062 } | 2132 } | 
| 2063 connection.onDetach = () => _activeSockets.remove(connection._socketConn); | 2133 connection.onDetach = () => _activeSockets.remove(connection._socketConn); | 
| 2064 | 2134 | 
| 2135 // Check to see if a proxy server should be used for this connection. | |
| 2136 _ProxyConfiguration proxyConfiguration = const _ProxyConfiguration.direct(); | |
| 2137 if (_findProxy != null) { | |
| 2138 // TODO(sgjesse): Keep a map of these as normally only a few | |
| 2139 // configuration strings will be used. | |
| 2140 proxyConfiguration = new _ProxyConfiguration(_findProxy(url)); | |
| 2141 } | |
| 2142 | |
| 2143 // Determine the actual host to connect to. | |
| 2144 String connectHost; | |
| 2145 int connectPort; | |
| 2146 _Proxy proxy = proxyConfiguration.proxies[0]; | |
| 2147 if (proxy.direct) { | |
| 2148 connectHost = host; | |
| 2149 connectPort = port; | |
| 2150 } else { | |
| 2151 connectHost = proxy.host; | |
| 2152 connectPort = proxy.port; | |
| 2153 } | |
| 2154 | |
| 2065 // If there are active connections for this key get the first one | 2155 // If there are active connections for this key get the first one | 
| 2066 // otherwise create a new one. | 2156 // otherwise create a new one. | 
| 2067 String key = _connectionKey(host, port); | 2157 String key = _connectionKey(connectHost, connectPort); | 
| 2068 Queue socketConnections = _openSockets[key]; | 2158 Queue socketConnections = _openSockets[key]; | 
| 2069 if (socketConnections == null || socketConnections.isEmpty()) { | 2159 if (socketConnections == null || socketConnections.isEmpty()) { | 
| 2070 Socket socket = new Socket(host, port); | 2160 Socket socket = new Socket(connectHost, connectPort); | 
| 2071 // Until the connection is established handle connection errors | 2161 // Until the connection is established handle connection errors | 
| 2072 // here as the HttpClientConnection object is not yet associated | 2162 // here as the HttpClientConnection object is not yet associated | 
| 2073 // with the socket. | 2163 // with the socket. | 
| 2074 socket.onError = (e) { | 2164 socket.onError = (e) { | 
| 2075 // Report the error through the HttpClientConnection object to | 2165 // Report the error through the HttpClientConnection object to | 
| 2076 // the client. | 2166 // the client. | 
| 2077 connection._onError(e); | 2167 connection._onError(e); | 
| 2078 }; | 2168 }; | 
| 2079 socket.onConnect = () { | 2169 socket.onConnect = () { | 
| 2080 // When the connection is established, clear the error | 2170 // When the connection is established, clear the error | 
| 2081 // callback as it will now be handled by the | 2171 // callback as it will now be handled by the | 
| 2082 // HttpClientConnection object which will be associated with | 2172 // HttpClientConnection object which will be associated with | 
| 2083 // the connected socket. | 2173 // the connected socket. | 
| 2084 socket.onError = null; | 2174 socket.onError = null; | 
| 2085 _SocketConnection socketConn = | 2175 _SocketConnection socketConn = | 
| 2086 new _SocketConnection(host, port, socket); | 2176 new _SocketConnection(connectHost, connectPort, socket); | 
| 2087 _activeSockets.add(socketConn); | 2177 _activeSockets.add(socketConn); | 
| 2088 _connectionOpened(socketConn, connection); | 2178 _connectionOpened(socketConn, | 
| 2179 connection, | |
| 2180 !proxyConfiguration.proxies[0].direct); | |
| 
Mads Ager (google)
2012/10/08 16:59:39
Just !proxy.direct?
 
Søren Gjesse
2012/10/09 14:05:22
Already fixed.
 | |
| 2089 }; | 2181 }; | 
| 2090 } else { | 2182 } else { | 
| 2091 _SocketConnection socketConn = socketConnections.removeFirst(); | 2183 _SocketConnection socketConn = socketConnections.removeFirst(); | 
| 2092 _activeSockets.add(socketConn); | 2184 _activeSockets.add(socketConn); | 
| 2093 new Timer(0, (ignored) => _connectionOpened(socketConn, connection)); | 2185 new Timer(0, (ignored) => | 
| 2186 _connectionOpened(socketConn, | |
| 2187 connection, | |
| 2188 !proxyConfiguration.proxies[0].direct)); | |
| 
Mads Ager (google)
2012/10/08 16:59:39
!proxy.direct.
 
Søren Gjesse
2012/10/09 14:05:22
Already fixed.
 | |
| 2094 | 2189 | 
| 2095 // Get rid of eviction timer if there are no more active connections. | 2190 // Get rid of eviction timer if there are no more active connections. | 
| 2096 if (socketConnections.isEmpty()) _openSockets.remove(key); | 2191 if (socketConnections.isEmpty()) _openSockets.remove(key); | 
| 2097 if (_openSockets.isEmpty()) _cancelEvictionTimer(); | 2192 if (_openSockets.isEmpty()) _cancelEvictionTimer(); | 
| 2098 } | 2193 } | 
| 2099 | 2194 | 
| 2100 return connection; | 2195 return connection; | 
| 2101 } | 2196 } | 
| 2102 | 2197 | 
| 2103 void _returnSocketConnection(_SocketConnection socketConn) { | 2198 void _returnSocketConnection(_SocketConnection socketConn) { | 
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2181 | 2276 | 
| 2182 | 2277 | 
| 2183 class _RedirectInfo implements RedirectInfo { | 2278 class _RedirectInfo implements RedirectInfo { | 
| 2184 const _RedirectInfo(int this.statusCode, | 2279 const _RedirectInfo(int this.statusCode, | 
| 2185 String this.method, | 2280 String this.method, | 
| 2186 Uri this.location); | 2281 Uri this.location); | 
| 2187 final int statusCode; | 2282 final int statusCode; | 
| 2188 final String method; | 2283 final String method; | 
| 2189 final Uri location; | 2284 final Uri location; | 
| 2190 } | 2285 } | 
| OLD | NEW |