Chromium Code Reviews| 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>() { | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |