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 |