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

Side by Side Diff: third_party/requests/packages/urllib3/poolmanager.py

Issue 25004007: Update 'requests' lib to v2.0. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/swarm_client
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 # urllib3/poolmanager.py 1 # urllib3/poolmanager.py
2 # Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt) 2 # Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt)
3 # 3 #
4 # This module is part of urllib3 and is released under 4 # This module is part of urllib3 and is released under
5 # the MIT License: http://www.opensource.org/licenses/mit-license.php 5 # the MIT License: http://www.opensource.org/licenses/mit-license.php
6 6
7 import logging 7 import logging
8 8
9 try: # Python 3
10 from urllib.parse import urljoin
11 except ImportError:
12 from urlparse import urljoin
13
9 from ._collections import RecentlyUsedContainer 14 from ._collections import RecentlyUsedContainer
10 from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool 15 from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool
11 from .connectionpool import connection_from_url, port_by_scheme 16 from .connectionpool import port_by_scheme
12 from .request import RequestMethods 17 from .request import RequestMethods
13 from .util import parse_url 18 from .util import parse_url
14 19
15 20
16 __all__ = ['PoolManager', 'ProxyManager', 'proxy_from_url'] 21 __all__ = ['PoolManager', 'ProxyManager', 'proxy_from_url']
17 22
18 23
19 pool_classes_by_scheme = { 24 pool_classes_by_scheme = {
20 'http': HTTPConnectionPool, 25 'http': HTTPConnectionPool,
21 'https': HTTPSConnectionPool, 26 'https': HTTPSConnectionPool,
(...skipping 26 matching lines...) Expand all
48 53
49 >>> manager = PoolManager(num_pools=2) 54 >>> manager = PoolManager(num_pools=2)
50 >>> r = manager.request('GET', 'http://google.com/') 55 >>> r = manager.request('GET', 'http://google.com/')
51 >>> r = manager.request('GET', 'http://google.com/mail') 56 >>> r = manager.request('GET', 'http://google.com/mail')
52 >>> r = manager.request('GET', 'http://yahoo.com/') 57 >>> r = manager.request('GET', 'http://yahoo.com/')
53 >>> len(manager.pools) 58 >>> len(manager.pools)
54 2 59 2
55 60
56 """ 61 """
57 62
63 proxy = None
64
58 def __init__(self, num_pools=10, headers=None, **connection_pool_kw): 65 def __init__(self, num_pools=10, headers=None, **connection_pool_kw):
59 RequestMethods.__init__(self, headers) 66 RequestMethods.__init__(self, headers)
60 self.connection_pool_kw = connection_pool_kw 67 self.connection_pool_kw = connection_pool_kw
61 self.pools = RecentlyUsedContainer(num_pools, 68 self.pools = RecentlyUsedContainer(num_pools,
62 dispose_func=lambda p: p.close()) 69 dispose_func=lambda p: p.close())
63 70
64 def _new_pool(self, scheme, host, port): 71 def _new_pool(self, scheme, host, port):
65 """ 72 """
66 Create a new :class:`ConnectionPool` based on host, port and scheme. 73 Create a new :class:`ConnectionPool` based on host, port and scheme.
67 74
(...skipping 19 matching lines...) Expand all
87 """ 94 """
88 self.pools.clear() 95 self.pools.clear()
89 96
90 def connection_from_host(self, host, port=None, scheme='http'): 97 def connection_from_host(self, host, port=None, scheme='http'):
91 """ 98 """
92 Get a :class:`ConnectionPool` based on the host, port, and scheme. 99 Get a :class:`ConnectionPool` based on the host, port, and scheme.
93 100
94 If ``port`` isn't given, it will be derived from the ``scheme`` using 101 If ``port`` isn't given, it will be derived from the ``scheme`` using
95 ``urllib3.connectionpool.port_by_scheme``. 102 ``urllib3.connectionpool.port_by_scheme``.
96 """ 103 """
104
97 scheme = scheme or 'http' 105 scheme = scheme or 'http'
106
98 port = port or port_by_scheme.get(scheme, 80) 107 port = port or port_by_scheme.get(scheme, 80)
99 108
100 pool_key = (scheme, host, port) 109 pool_key = (scheme, host, port)
101 110
102 # If the scheme, host, or port doesn't match existing open connections, 111 with self.pools.lock:
103 # open a new ConnectionPool. 112 # If the scheme, host, or port doesn't match existing open
104 pool = self.pools.get(pool_key) 113 # connections, open a new ConnectionPool.
105 if pool: 114 pool = self.pools.get(pool_key)
106 return pool 115 if pool:
116 return pool
107 117
108 # Make a fresh ConnectionPool of the desired type 118 # Make a fresh ConnectionPool of the desired type
109 pool = self._new_pool(scheme, host, port) 119 pool = self._new_pool(scheme, host, port)
110 self.pools[pool_key] = pool 120 self.pools[pool_key] = pool
111 return pool 121 return pool
112 122
113 def connection_from_url(self, url): 123 def connection_from_url(self, url):
114 """ 124 """
115 Similar to :func:`urllib3.connectionpool.connection_from_url` but 125 Similar to :func:`urllib3.connectionpool.connection_from_url` but
116 doesn't pass any additional parameters to the 126 doesn't pass any additional parameters to the
117 :class:`urllib3.connectionpool.ConnectionPool` constructor. 127 :class:`urllib3.connectionpool.ConnectionPool` constructor.
118 128
119 Additional parameters are taken from the :class:`.PoolManager` 129 Additional parameters are taken from the :class:`.PoolManager`
120 constructor. 130 constructor.
(...skipping 11 matching lines...) Expand all
132 :class:`urllib3.connectionpool.ConnectionPool` can be chosen for it. 142 :class:`urllib3.connectionpool.ConnectionPool` can be chosen for it.
133 """ 143 """
134 u = parse_url(url) 144 u = parse_url(url)
135 conn = self.connection_from_host(u.host, port=u.port, scheme=u.scheme) 145 conn = self.connection_from_host(u.host, port=u.port, scheme=u.scheme)
136 146
137 kw['assert_same_host'] = False 147 kw['assert_same_host'] = False
138 kw['redirect'] = False 148 kw['redirect'] = False
139 if 'headers' not in kw: 149 if 'headers' not in kw:
140 kw['headers'] = self.headers 150 kw['headers'] = self.headers
141 151
142 response = conn.urlopen(method, u.request_uri, **kw) 152 if self.proxy is not None and u.scheme == "http":
153 response = conn.urlopen(method, url, **kw)
154 else:
155 response = conn.urlopen(method, u.request_uri, **kw)
143 156
144 redirect_location = redirect and response.get_redirect_location() 157 redirect_location = redirect and response.get_redirect_location()
145 if not redirect_location: 158 if not redirect_location:
146 return response 159 return response
147 160
161 # Support relative URLs for redirecting.
162 redirect_location = urljoin(url, redirect_location)
163
164 # RFC 2616, Section 10.3.4
148 if response.status == 303: 165 if response.status == 303:
149 method = 'GET' 166 method = 'GET'
150 167
151 log.info("Redirecting %s -> %s" % (url, redirect_location)) 168 log.info("Redirecting %s -> %s" % (url, redirect_location))
152 kw['retries'] = kw.get('retries', 3) - 1 # Persist retries countdown 169 kw['retries'] = kw.get('retries', 3) - 1 # Persist retries countdown
153 kw['redirect'] = redirect 170 kw['redirect'] = redirect
154 return self.urlopen(method, redirect_location, **kw) 171 return self.urlopen(method, redirect_location, **kw)
155 172
156 173
157 class ProxyManager(RequestMethods): 174 class ProxyManager(PoolManager):
158 """ 175 """
159 Given a ConnectionPool to a proxy, the ProxyManager's ``urlopen`` method 176 Behaves just like :class:`PoolManager`, but sends all requests through
160 will make requests to any url through the defined proxy. The ProxyManager 177 the defined proxy, using the CONNECT method for HTTPS URLs.
161 class will automatically set the 'Host' header if it is not provided. 178
179 :param poxy_url:
180 The URL of the proxy to be used.
181
182 :param proxy_headers:
183 A dictionary contaning headers that will be sent to the proxy. In case
184 of HTTP they are being sent with each request, while in the
185 HTTPS/CONNECT case they are sent only once. Could be used for proxy
186 authentication.
187
188 Example:
189 >>> proxy = urllib3.ProxyManager('http://localhost:3128/')
190 >>> r1 = proxy.request('GET', 'http://google.com/')
191 >>> r2 = proxy.request('GET', 'http://httpbin.org/')
192 >>> len(proxy.pools)
193 1
194 >>> r3 = proxy.request('GET', 'https://httpbin.org/')
195 >>> r4 = proxy.request('GET', 'https://twitter.com/')
196 >>> len(proxy.pools)
197 3
198
162 """ 199 """
163 200
164 def __init__(self, proxy_pool): 201 def __init__(self, proxy_url, num_pools=10, headers=None,
165 self.proxy_pool = proxy_pool 202 proxy_headers=None, **connection_pool_kw):
203
204 if isinstance(proxy_url, HTTPConnectionPool):
205 proxy_url = '%s://%s:%i' % (proxy_url.scheme, proxy_url.host,
206 proxy_url.port)
207 proxy = parse_url(proxy_url)
208 if not proxy.port:
209 port = port_by_scheme.get(proxy.scheme, 80)
210 proxy = proxy._replace(port=port)
211 self.proxy = proxy
212 self.proxy_headers = proxy_headers or {}
213 assert self.proxy.scheme in ("http", "https"), \
214 'Not supported proxy scheme %s' % self.proxy.scheme
215 connection_pool_kw['_proxy'] = self.proxy
216 connection_pool_kw['_proxy_headers'] = self.proxy_headers
217 super(ProxyManager, self).__init__(
218 num_pools, headers, **connection_pool_kw)
219
220 def connection_from_host(self, host, port=None, scheme='http'):
221 if scheme == "https":
222 return super(ProxyManager, self).connection_from_host(
223 host, port, scheme)
224
225 return super(ProxyManager, self).connection_from_host(
226 self.proxy.host, self.proxy.port, self.proxy.scheme)
166 227
167 def _set_proxy_headers(self, url, headers=None): 228 def _set_proxy_headers(self, url, headers=None):
168 """ 229 """
169 Sets headers needed by proxies: specifically, the Accept and Host 230 Sets headers needed by proxies: specifically, the Accept and Host
170 headers. Only sets headers not provided by the user. 231 headers. Only sets headers not provided by the user.
171 """ 232 """
172 headers_ = {'Accept': '*/*'} 233 headers_ = {'Accept': '*/*'}
173 234
174 host = parse_url(url).host 235 netloc = parse_url(url).netloc
175 if host: 236 if netloc:
176 headers_['Host'] = host 237 headers_['Host'] = netloc
177 238
178 if headers: 239 if headers:
179 headers_.update(headers) 240 headers_.update(headers)
180
181 return headers_ 241 return headers_
182 242
183 def urlopen(self, method, url, **kw): 243 def urlopen(self, method, url, redirect=True, **kw):
184 "Same as HTTP(S)ConnectionPool.urlopen, ``url`` must be absolute." 244 "Same as HTTP(S)ConnectionPool.urlopen, ``url`` must be absolute."
185 kw['assert_same_host'] = False 245 u = parse_url(url)
186 kw['headers'] = self._set_proxy_headers(url, headers=kw.get('headers')) 246
187 return self.proxy_pool.urlopen(method, url, **kw) 247 if u.scheme == "http":
248 # It's too late to set proxy headers on per-request basis for
249 # tunnelled HTTPS connections, should use
250 # constructor's proxy_headers instead.
251 kw['headers'] = self._set_proxy_headers(url, kw.get('headers',
252 self.headers))
253 kw['headers'].update(self.proxy_headers)
254
255 return super(ProxyManager, self).urlopen(method, url, redirect, **kw)
188 256
189 257
190 def proxy_from_url(url, **pool_kw): 258 def proxy_from_url(url, **kw):
191 proxy_pool = connection_from_url(url, **pool_kw) 259 return ProxyManager(proxy_url=url, **kw)
192 return ProxyManager(proxy_pool)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698