| 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 2020 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2031 static const String PROXY_PREFIX = "PROXY "; | 2031 static const String PROXY_PREFIX = "PROXY "; |
| 2032 static const String DIRECT_PREFIX = "DIRECT"; | 2032 static const String DIRECT_PREFIX = "DIRECT"; |
| 2033 | 2033 |
| 2034 _ProxyConfiguration(String configuration) : proxies = new List<_Proxy>() { | 2034 _ProxyConfiguration(String configuration) : proxies = new List<_Proxy>() { |
| 2035 if (configuration == null) { | 2035 if (configuration == null) { |
| 2036 throw new HttpException("Invalid proxy configuration $configuration"); | 2036 throw new HttpException("Invalid proxy configuration $configuration"); |
| 2037 } | 2037 } |
| 2038 List<String> list = configuration.split(";"); | 2038 List<String> list = configuration.split(";"); |
| 2039 list.forEach((String proxy) { | 2039 list.forEach((String proxy) { |
| 2040 proxy = proxy.trim(); | 2040 proxy = proxy.trim(); |
| 2041 if (!proxy.isEmpty()) { | 2041 if (!proxy.isEmpty) { |
| 2042 if (proxy.startsWith(PROXY_PREFIX)) { | 2042 if (proxy.startsWith(PROXY_PREFIX)) { |
| 2043 int colon = proxy.indexOf(":"); | 2043 int colon = proxy.indexOf(":"); |
| 2044 if (colon == -1 || colon == 0 || colon == proxy.length - 1) { | 2044 if (colon == -1 || colon == 0 || colon == proxy.length - 1) { |
| 2045 throw new HttpException( | 2045 throw new HttpException( |
| 2046 "Invalid proxy configuration $configuration"); | 2046 "Invalid proxy configuration $configuration"); |
| 2047 } | 2047 } |
| 2048 // Skip the "PROXY " prefix. | 2048 // Skip the "PROXY " prefix. |
| 2049 String host = proxy.substring(PROXY_PREFIX.length, colon).trim(); | 2049 String host = proxy.substring(PROXY_PREFIX.length, colon).trim(); |
| 2050 String portString = proxy.substring(colon + 1).trim(); | 2050 String portString = proxy.substring(colon + 1).trim(); |
| 2051 int port; | 2051 int port; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2093 // TODO(sgjesse): The path set here can contain both query and | 2093 // TODO(sgjesse): The path set here can contain both query and |
| 2094 // fragment. They should be cracked and set correctly. | 2094 // fragment. They should be cracked and set correctly. |
| 2095 return _open(method, new Uri.fromComponents( | 2095 return _open(method, new Uri.fromComponents( |
| 2096 scheme: "http", domain: host, port: port, path: path)); | 2096 scheme: "http", domain: host, port: port, path: path)); |
| 2097 } | 2097 } |
| 2098 | 2098 |
| 2099 HttpClientConnection _open(String method, | 2099 HttpClientConnection _open(String method, |
| 2100 Uri uri, | 2100 Uri uri, |
| 2101 [_HttpClientConnection connection]) { | 2101 [_HttpClientConnection connection]) { |
| 2102 if (_shutdown) throw new HttpException("HttpClient shutdown"); | 2102 if (_shutdown) throw new HttpException("HttpClient shutdown"); |
| 2103 if (method == null || uri.domain.isEmpty()) { | 2103 if (method == null || uri.domain.isEmpty) { |
| 2104 throw new ArgumentError(null); | 2104 throw new ArgumentError(null); |
| 2105 } | 2105 } |
| 2106 return _prepareHttpClientConnection(method, uri, connection); | 2106 return _prepareHttpClientConnection(method, uri, connection); |
| 2107 } | 2107 } |
| 2108 | 2108 |
| 2109 HttpClientConnection openUrl(String method, Uri url) { | 2109 HttpClientConnection openUrl(String method, Uri url) { |
| 2110 return _openUrl(method, url); | 2110 return _openUrl(method, url); |
| 2111 } | 2111 } |
| 2112 | 2112 |
| 2113 HttpClientConnection _openUrl(String method, | 2113 HttpClientConnection _openUrl(String method, |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2131 HttpClientConnection post(String host, int port, String path) { | 2131 HttpClientConnection post(String host, int port, String path) { |
| 2132 return open("POST", host, port, path); | 2132 return open("POST", host, port, path); |
| 2133 } | 2133 } |
| 2134 | 2134 |
| 2135 HttpClientConnection postUrl(Uri url) => _openUrl("POST", url); | 2135 HttpClientConnection postUrl(Uri url) => _openUrl("POST", url); |
| 2136 | 2136 |
| 2137 set findProxy(String f(Uri uri)) => _findProxy = f; | 2137 set findProxy(String f(Uri uri)) => _findProxy = f; |
| 2138 | 2138 |
| 2139 void shutdown() { | 2139 void shutdown() { |
| 2140 _openSockets.forEach((String key, Queue<_SocketConnection> connections) { | 2140 _openSockets.forEach((String key, Queue<_SocketConnection> connections) { |
| 2141 while (!connections.isEmpty()) { | 2141 while (!connections.isEmpty) { |
| 2142 _SocketConnection socketConn = connections.removeFirst(); | 2142 _SocketConnection socketConn = connections.removeFirst(); |
| 2143 socketConn._socket.close(); | 2143 socketConn._socket.close(); |
| 2144 } | 2144 } |
| 2145 }); | 2145 }); |
| 2146 _activeSockets.forEach((_SocketConnection socketConn) { | 2146 _activeSockets.forEach((_SocketConnection socketConn) { |
| 2147 socketConn._socket.close(); | 2147 socketConn._socket.close(); |
| 2148 }); | 2148 }); |
| 2149 if (_evictionTimer != null) _cancelEvictionTimer(); | 2149 if (_evictionTimer != null) _cancelEvictionTimer(); |
| 2150 _shutdown = true; | 2150 _shutdown = true; |
| 2151 } | 2151 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2195 connectPort = port; | 2195 connectPort = port; |
| 2196 } else { | 2196 } else { |
| 2197 connectHost = proxy.host; | 2197 connectHost = proxy.host; |
| 2198 connectPort = proxy.port; | 2198 connectPort = proxy.port; |
| 2199 } | 2199 } |
| 2200 | 2200 |
| 2201 // If there are active connections for this key get the first one | 2201 // If there are active connections for this key get the first one |
| 2202 // otherwise create a new one. | 2202 // otherwise create a new one. |
| 2203 String key = _connectionKey(connectHost, connectPort); | 2203 String key = _connectionKey(connectHost, connectPort); |
| 2204 Queue socketConnections = _openSockets[key]; | 2204 Queue socketConnections = _openSockets[key]; |
| 2205 if (socketConnections == null || socketConnections.isEmpty()) { | 2205 if (socketConnections == null || socketConnections.isEmpty) { |
| 2206 Socket socket = new Socket(connectHost, connectPort); | 2206 Socket socket = new Socket(connectHost, connectPort); |
| 2207 // Until the connection is established handle connection errors | 2207 // Until the connection is established handle connection errors |
| 2208 // here as the HttpClientConnection object is not yet associated | 2208 // here as the HttpClientConnection object is not yet associated |
| 2209 // with the socket. | 2209 // with the socket. |
| 2210 socket.onError = (e) { | 2210 socket.onError = (e) { |
| 2211 proxyIndex++; | 2211 proxyIndex++; |
| 2212 if (proxyIndex < proxyConfiguration.proxies.length) { | 2212 if (proxyIndex < proxyConfiguration.proxies.length) { |
| 2213 // Try the next proxy in the list. | 2213 // Try the next proxy in the list. |
| 2214 _establishConnection(host, port, proxyConfiguration, proxyIndex); | 2214 _establishConnection(host, port, proxyConfiguration, proxyIndex); |
| 2215 } else { | 2215 } else { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2229 _activeSockets.add(socketConn); | 2229 _activeSockets.add(socketConn); |
| 2230 _connectionOpened(socketConn, connection, !proxy.isDirect); | 2230 _connectionOpened(socketConn, connection, !proxy.isDirect); |
| 2231 }; | 2231 }; |
| 2232 } else { | 2232 } else { |
| 2233 _SocketConnection socketConn = socketConnections.removeFirst(); | 2233 _SocketConnection socketConn = socketConnections.removeFirst(); |
| 2234 _activeSockets.add(socketConn); | 2234 _activeSockets.add(socketConn); |
| 2235 new Timer(0, (ignored) => | 2235 new Timer(0, (ignored) => |
| 2236 _connectionOpened(socketConn, connection, !proxy.isDirect)); | 2236 _connectionOpened(socketConn, connection, !proxy.isDirect)); |
| 2237 | 2237 |
| 2238 // Get rid of eviction timer if there are no more active connections. | 2238 // Get rid of eviction timer if there are no more active connections. |
| 2239 if (socketConnections.isEmpty()) _openSockets.remove(key); | 2239 if (socketConnections.isEmpty) _openSockets.remove(key); |
| 2240 if (_openSockets.isEmpty()) _cancelEvictionTimer(); | 2240 if (_openSockets.isEmpty) _cancelEvictionTimer(); |
| 2241 } | 2241 } |
| 2242 } | 2242 } |
| 2243 | 2243 |
| 2244 // Find the TCP host and port. | 2244 // Find the TCP host and port. |
| 2245 String host = url.domain; | 2245 String host = url.domain; |
| 2246 int port = url.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : url.port; | 2246 int port = url.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : url.port; |
| 2247 | 2247 |
| 2248 // Create a new connection object if we are not re-using an existing one. | 2248 // Create a new connection object if we are not re-using an existing one. |
| 2249 if (connection == null) { | 2249 if (connection == null) { |
| 2250 connection = new _HttpClientConnection(this); | 2250 connection = new _HttpClientConnection(this); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2286 | 2286 |
| 2287 // If there is currently no eviction timer start one. | 2287 // If there is currently no eviction timer start one. |
| 2288 if (_evictionTimer == null) { | 2288 if (_evictionTimer == null) { |
| 2289 void _handleEviction(Timer timer) { | 2289 void _handleEviction(Timer timer) { |
| 2290 Date now = new Date.now(); | 2290 Date now = new Date.now(); |
| 2291 List<String> emptyKeys = new List<String>(); | 2291 List<String> emptyKeys = new List<String>(); |
| 2292 _openSockets.forEach( | 2292 _openSockets.forEach( |
| 2293 void _(String key, Queue<_SocketConnection> connections) { | 2293 void _(String key, Queue<_SocketConnection> connections) { |
| 2294 // As returned connections are added at the head of the | 2294 // As returned connections are added at the head of the |
| 2295 // list remove from the tail. | 2295 // list remove from the tail. |
| 2296 while (!connections.isEmpty()) { | 2296 while (!connections.isEmpty) { |
| 2297 _SocketConnection socketConn = connections.last(); | 2297 _SocketConnection socketConn = connections.last(); |
| 2298 if (socketConn._idleTime(now).inMilliseconds > | 2298 if (socketConn._idleTime(now).inMilliseconds > |
| 2299 DEFAULT_EVICTION_TIMEOUT) { | 2299 DEFAULT_EVICTION_TIMEOUT) { |
| 2300 connections.removeLast(); | 2300 connections.removeLast(); |
| 2301 socketConn._socket.close(); | 2301 socketConn._socket.close(); |
| 2302 if (connections.isEmpty()) emptyKeys.add(key); | 2302 if (connections.isEmpty) emptyKeys.add(key); |
| 2303 } else { | 2303 } else { |
| 2304 break; | 2304 break; |
| 2305 } | 2305 } |
| 2306 } | 2306 } |
| 2307 }); | 2307 }); |
| 2308 | 2308 |
| 2309 // Remove the keys for which here are no more open connections. | 2309 // Remove the keys for which here are no more open connections. |
| 2310 emptyKeys.forEach((String key) => _openSockets.remove(key)); | 2310 emptyKeys.forEach((String key) => _openSockets.remove(key)); |
| 2311 | 2311 |
| 2312 // If all connections where evicted cancel the eviction timer. | 2312 // If all connections where evicted cancel the eviction timer. |
| 2313 if (_openSockets.isEmpty()) _cancelEvictionTimer(); | 2313 if (_openSockets.isEmpty) _cancelEvictionTimer(); |
| 2314 } | 2314 } |
| 2315 _evictionTimer = new Timer.repeating(10000, _handleEviction); | 2315 _evictionTimer = new Timer.repeating(10000, _handleEviction); |
| 2316 } | 2316 } |
| 2317 | 2317 |
| 2318 // Return connection. | 2318 // Return connection. |
| 2319 _activeSockets.remove(socketConn); | 2319 _activeSockets.remove(socketConn); |
| 2320 sockets.addFirst(socketConn); | 2320 sockets.addFirst(socketConn); |
| 2321 } | 2321 } |
| 2322 | 2322 |
| 2323 Function _onOpen; | 2323 Function _onOpen; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2346 | 2346 |
| 2347 | 2347 |
| 2348 class _RedirectInfo implements RedirectInfo { | 2348 class _RedirectInfo implements RedirectInfo { |
| 2349 const _RedirectInfo(int this.statusCode, | 2349 const _RedirectInfo(int this.statusCode, |
| 2350 String this.method, | 2350 String this.method, |
| 2351 Uri this.location); | 2351 Uri this.location); |
| 2352 final int statusCode; | 2352 final int statusCode; |
| 2353 final String method; | 2353 final String method; |
| 2354 final Uri location; | 2354 final Uri location; |
| 2355 } | 2355 } |
| OLD | NEW |