Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/requests/adapters.py: 23%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

248 statements  

1""" 

2requests.adapters 

3~~~~~~~~~~~~~~~~~ 

4 

5This module contains the transport adapters that Requests uses to define 

6and maintain connections. 

7""" 

8 

9import os.path 

10import socket # noqa: F401 

11import typing 

12import warnings 

13 

14from urllib3.exceptions import ClosedPoolError, ConnectTimeoutError 

15from urllib3.exceptions import HTTPError as _HTTPError 

16from urllib3.exceptions import InvalidHeader as _InvalidHeader 

17from urllib3.exceptions import ( 

18 LocationValueError, 

19 MaxRetryError, 

20 NewConnectionError, 

21 ProtocolError, 

22) 

23from urllib3.exceptions import ProxyError as _ProxyError 

24from urllib3.exceptions import ReadTimeoutError, ResponseError 

25from urllib3.exceptions import SSLError as _SSLError 

26from urllib3.poolmanager import PoolManager, proxy_from_url 

27from urllib3.util import Timeout as TimeoutSauce 

28from urllib3.util import parse_url 

29from urllib3.util.retry import Retry 

30from urllib3.util.ssl_ import create_urllib3_context 

31 

32from .auth import _basic_auth_str 

33from .compat import basestring, urlparse 

34from .cookies import extract_cookies_to_jar 

35from .exceptions import ( 

36 ConnectionError, 

37 ConnectTimeout, 

38 InvalidHeader, 

39 InvalidProxyURL, 

40 InvalidSchema, 

41 InvalidURL, 

42 ProxyError, 

43 ReadTimeout, 

44 RetryError, 

45 SSLError, 

46) 

47from .models import Response 

48from .structures import CaseInsensitiveDict 

49from .utils import ( 

50 DEFAULT_CA_BUNDLE_PATH, 

51 extract_zipped_paths, 

52 get_auth_from_url, 

53 get_encoding_from_headers, 

54 prepend_scheme_if_needed, 

55 select_proxy, 

56 urldefragauth, 

57) 

58 

59try: 

60 from urllib3.contrib.socks import SOCKSProxyManager 

61except ImportError: 

62 

63 def SOCKSProxyManager(*args, **kwargs): 

64 raise InvalidSchema("Missing dependencies for SOCKS support.") 

65 

66 

67if typing.TYPE_CHECKING: 

68 from .models import PreparedRequest 

69 

70 

71DEFAULT_POOLBLOCK = False 

72DEFAULT_POOLSIZE = 10 

73DEFAULT_RETRIES = 0 

74DEFAULT_POOL_TIMEOUT = None 

75 

76 

77try: 

78 import ssl # noqa: F401 

79 

80 _preloaded_ssl_context = create_urllib3_context() 

81 _preloaded_ssl_context.load_verify_locations( 

82 extract_zipped_paths(DEFAULT_CA_BUNDLE_PATH) 

83 ) 

84except ImportError: 

85 # Bypass default SSLContext creation when Python 

86 # interpreter isn't built with the ssl module. 

87 _preloaded_ssl_context = None 

88 

89 

90def _urllib3_request_context( 

91 request: "PreparedRequest", 

92 verify: "bool | str | None", 

93 client_cert: "typing.Tuple[str, str] | str | None", 

94 poolmanager: "PoolManager", 

95) -> "(typing.Dict[str, typing.Any], typing.Dict[str, typing.Any])": 

96 host_params = {} 

97 pool_kwargs = {} 

98 parsed_request_url = urlparse(request.url) 

99 scheme = parsed_request_url.scheme.lower() 

100 port = parsed_request_url.port 

101 

102 # Determine if we have and should use our default SSLContext 

103 # to optimize performance on standard requests. 

104 poolmanager_kwargs = getattr(poolmanager, "connection_pool_kw", {}) 

105 has_poolmanager_ssl_context = poolmanager_kwargs.get("ssl_context") 

106 should_use_default_ssl_context = ( 

107 _preloaded_ssl_context is not None and not has_poolmanager_ssl_context 

108 ) 

109 

110 cert_reqs = "CERT_REQUIRED" 

111 if verify is False: 

112 cert_reqs = "CERT_NONE" 

113 elif verify is True and should_use_default_ssl_context: 

114 pool_kwargs["ssl_context"] = _preloaded_ssl_context 

115 elif isinstance(verify, str): 

116 if not os.path.isdir(verify): 

117 pool_kwargs["ca_certs"] = verify 

118 else: 

119 pool_kwargs["ca_cert_dir"] = verify 

120 pool_kwargs["cert_reqs"] = cert_reqs 

121 if client_cert is not None: 

122 if isinstance(client_cert, tuple) and len(client_cert) == 2: 

123 pool_kwargs["cert_file"] = client_cert[0] 

124 pool_kwargs["key_file"] = client_cert[1] 

125 else: 

126 # According to our docs, we allow users to specify just the client 

127 # cert path 

128 pool_kwargs["cert_file"] = client_cert 

129 host_params = { 

130 "scheme": scheme, 

131 "host": parsed_request_url.hostname, 

132 "port": port, 

133 } 

134 return host_params, pool_kwargs 

135 

136 

137class BaseAdapter: 

138 """The Base Transport Adapter""" 

139 

140 def __init__(self): 

141 super().__init__() 

142 

143 def send( 

144 self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None 

145 ): 

146 """Sends PreparedRequest object. Returns Response object. 

147 

148 :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. 

149 :param stream: (optional) Whether to stream the request content. 

150 :param timeout: (optional) How long to wait for the server to send 

151 data before giving up, as a float, or a :ref:`(connect timeout, 

152 read timeout) <timeouts>` tuple. 

153 :type timeout: float or tuple 

154 :param verify: (optional) Either a boolean, in which case it controls whether we verify 

155 the server's TLS certificate, or a string, in which case it must be a path 

156 to a CA bundle to use 

157 :param cert: (optional) Any user-provided SSL certificate to be trusted. 

158 :param proxies: (optional) The proxies dictionary to apply to the request. 

159 """ 

160 raise NotImplementedError 

161 

162 def close(self): 

163 """Cleans up adapter specific items.""" 

164 raise NotImplementedError 

165 

166 

167class HTTPAdapter(BaseAdapter): 

168 """The built-in HTTP Adapter for urllib3. 

169 

170 Provides a general-case interface for Requests sessions to contact HTTP and 

171 HTTPS urls by implementing the Transport Adapter interface. This class will 

172 usually be created by the :class:`Session <Session>` class under the 

173 covers. 

174 

175 :param pool_connections: The number of urllib3 connection pools to cache. 

176 :param pool_maxsize: The maximum number of connections to save in the pool. 

177 :param max_retries: The maximum number of retries each connection 

178 should attempt. Note, this applies only to failed DNS lookups, socket 

179 connections and connection timeouts, never to requests where data has 

180 made it to the server. By default, Requests does not retry failed 

181 connections. If you need granular control over the conditions under 

182 which we retry a request, import urllib3's ``Retry`` class and pass 

183 that instead. 

184 :param pool_block: Whether the connection pool should block for connections. 

185 

186 Usage:: 

187 

188 >>> import requests 

189 >>> s = requests.Session() 

190 >>> a = requests.adapters.HTTPAdapter(max_retries=3) 

191 >>> s.mount('http://', a) 

192 """ 

193 

194 __attrs__ = [ 

195 "max_retries", 

196 "config", 

197 "_pool_connections", 

198 "_pool_maxsize", 

199 "_pool_block", 

200 ] 

201 

202 def __init__( 

203 self, 

204 pool_connections=DEFAULT_POOLSIZE, 

205 pool_maxsize=DEFAULT_POOLSIZE, 

206 max_retries=DEFAULT_RETRIES, 

207 pool_block=DEFAULT_POOLBLOCK, 

208 ): 

209 if max_retries == DEFAULT_RETRIES: 

210 self.max_retries = Retry(0, read=False) 

211 else: 

212 self.max_retries = Retry.from_int(max_retries) 

213 self.config = {} 

214 self.proxy_manager = {} 

215 

216 super().__init__() 

217 

218 self._pool_connections = pool_connections 

219 self._pool_maxsize = pool_maxsize 

220 self._pool_block = pool_block 

221 

222 self.init_poolmanager(pool_connections, pool_maxsize, block=pool_block) 

223 

224 def __getstate__(self): 

225 return {attr: getattr(self, attr, None) for attr in self.__attrs__} 

226 

227 def __setstate__(self, state): 

228 # Can't handle by adding 'proxy_manager' to self.__attrs__ because 

229 # self.poolmanager uses a lambda function, which isn't pickleable. 

230 self.proxy_manager = {} 

231 self.config = {} 

232 

233 for attr, value in state.items(): 

234 setattr(self, attr, value) 

235 

236 self.init_poolmanager( 

237 self._pool_connections, self._pool_maxsize, block=self._pool_block 

238 ) 

239 

240 def init_poolmanager( 

241 self, connections, maxsize, block=DEFAULT_POOLBLOCK, **pool_kwargs 

242 ): 

243 """Initializes a urllib3 PoolManager. 

244 

245 This method should not be called from user code, and is only 

246 exposed for use when subclassing the 

247 :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. 

248 

249 :param connections: The number of urllib3 connection pools to cache. 

250 :param maxsize: The maximum number of connections to save in the pool. 

251 :param block: Block when no free connections are available. 

252 :param pool_kwargs: Extra keyword arguments used to initialize the Pool Manager. 

253 """ 

254 # save these values for pickling 

255 self._pool_connections = connections 

256 self._pool_maxsize = maxsize 

257 self._pool_block = block 

258 

259 self.poolmanager = PoolManager( 

260 num_pools=connections, 

261 maxsize=maxsize, 

262 block=block, 

263 **pool_kwargs, 

264 ) 

265 

266 def proxy_manager_for(self, proxy, **proxy_kwargs): 

267 """Return urllib3 ProxyManager for the given proxy. 

268 

269 This method should not be called from user code, and is only 

270 exposed for use when subclassing the 

271 :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. 

272 

273 :param proxy: The proxy to return a urllib3 ProxyManager for. 

274 :param proxy_kwargs: Extra keyword arguments used to configure the Proxy Manager. 

275 :returns: ProxyManager 

276 :rtype: urllib3.ProxyManager 

277 """ 

278 if proxy in self.proxy_manager: 

279 manager = self.proxy_manager[proxy] 

280 elif proxy.lower().startswith("socks"): 

281 username, password = get_auth_from_url(proxy) 

282 manager = self.proxy_manager[proxy] = SOCKSProxyManager( 

283 proxy, 

284 username=username, 

285 password=password, 

286 num_pools=self._pool_connections, 

287 maxsize=self._pool_maxsize, 

288 block=self._pool_block, 

289 **proxy_kwargs, 

290 ) 

291 else: 

292 proxy_headers = self.proxy_headers(proxy) 

293 manager = self.proxy_manager[proxy] = proxy_from_url( 

294 proxy, 

295 proxy_headers=proxy_headers, 

296 num_pools=self._pool_connections, 

297 maxsize=self._pool_maxsize, 

298 block=self._pool_block, 

299 **proxy_kwargs, 

300 ) 

301 

302 return manager 

303 

304 def cert_verify(self, conn, url, verify, cert): 

305 """Verify a SSL certificate. This method should not be called from user 

306 code, and is only exposed for use when subclassing the 

307 :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. 

308 

309 :param conn: The urllib3 connection object associated with the cert. 

310 :param url: The requested URL. 

311 :param verify: Either a boolean, in which case it controls whether we verify 

312 the server's TLS certificate, or a string, in which case it must be a path 

313 to a CA bundle to use 

314 :param cert: The SSL certificate to verify. 

315 """ 

316 if url.lower().startswith("https") and verify: 

317 conn.cert_reqs = "CERT_REQUIRED" 

318 

319 # Only load the CA certificates if 'verify' is a string indicating the CA bundle to use. 

320 # Otherwise, if verify is a boolean, we don't load anything since 

321 # the connection will be using a context with the default certificates already loaded, 

322 # and this avoids a call to the slow load_verify_locations() 

323 if verify is not True: 

324 # `verify` must be a str with a path then 

325 cert_loc = verify 

326 

327 if not os.path.exists(cert_loc): 

328 raise OSError( 

329 f"Could not find a suitable TLS CA certificate bundle, " 

330 f"invalid path: {cert_loc}" 

331 ) 

332 

333 if not os.path.isdir(cert_loc): 

334 conn.ca_certs = cert_loc 

335 else: 

336 conn.ca_cert_dir = cert_loc 

337 else: 

338 conn.cert_reqs = "CERT_NONE" 

339 conn.ca_certs = None 

340 conn.ca_cert_dir = None 

341 

342 if cert: 

343 if not isinstance(cert, basestring): 

344 conn.cert_file = cert[0] 

345 conn.key_file = cert[1] 

346 else: 

347 conn.cert_file = cert 

348 conn.key_file = None 

349 if conn.cert_file and not os.path.exists(conn.cert_file): 

350 raise OSError( 

351 f"Could not find the TLS certificate file, " 

352 f"invalid path: {conn.cert_file}" 

353 ) 

354 if conn.key_file and not os.path.exists(conn.key_file): 

355 raise OSError( 

356 f"Could not find the TLS key file, invalid path: {conn.key_file}" 

357 ) 

358 

359 def build_response(self, req, resp): 

360 """Builds a :class:`Response <requests.Response>` object from a urllib3 

361 response. This should not be called from user code, and is only exposed 

362 for use when subclassing the 

363 :class:`HTTPAdapter <requests.adapters.HTTPAdapter>` 

364 

365 :param req: The :class:`PreparedRequest <PreparedRequest>` used to generate the response. 

366 :param resp: The urllib3 response object. 

367 :rtype: requests.Response 

368 """ 

369 response = Response() 

370 

371 # Fallback to None if there's no status_code, for whatever reason. 

372 response.status_code = getattr(resp, "status", None) 

373 

374 # Make headers case-insensitive. 

375 response.headers = CaseInsensitiveDict(getattr(resp, "headers", {})) 

376 

377 # Set encoding. 

378 response.encoding = get_encoding_from_headers(response.headers) 

379 response.raw = resp 

380 response.reason = response.raw.reason 

381 

382 if isinstance(req.url, bytes): 

383 response.url = req.url.decode("utf-8") 

384 else: 

385 response.url = req.url 

386 

387 # Add new cookies from the server. 

388 extract_cookies_to_jar(response.cookies, req, resp) 

389 

390 # Give the Response some context. 

391 response.request = req 

392 response.connection = self 

393 

394 return response 

395 

396 def build_connection_pool_key_attributes(self, request, verify, cert=None): 

397 """Build the PoolKey attributes used by urllib3 to return a connection. 

398 

399 This looks at the PreparedRequest, the user-specified verify value, 

400 and the value of the cert parameter to determine what PoolKey values 

401 to use to select a connection from a given urllib3 Connection Pool. 

402 

403 The SSL related pool key arguments are not consistently set. As of 

404 this writing, use the following to determine what keys may be in that 

405 dictionary: 

406 

407 * If ``verify`` is ``True``, ``"ssl_context"`` will be set and will be the 

408 default Requests SSL Context 

409 * If ``verify`` is ``False``, ``"ssl_context"`` will not be set but 

410 ``"cert_reqs"`` will be set 

411 * If ``verify`` is a string, (i.e., it is a user-specified trust bundle) 

412 ``"ca_certs"`` will be set if the string is not a directory recognized 

413 by :py:func:`os.path.isdir`, otherwise ``"ca_certs_dir"`` will be 

414 set. 

415 * If ``"cert"`` is specified, ``"cert_file"`` will always be set. If 

416 ``"cert"`` is a tuple with a second item, ``"key_file"`` will also 

417 be present 

418 

419 To override these settings, one may subclass this class, call this 

420 method and use the above logic to change parameters as desired. For 

421 example, if one wishes to use a custom :py:class:`ssl.SSLContext` one 

422 must both set ``"ssl_context"`` and based on what else they require, 

423 alter the other keys to ensure the desired behaviour. 

424 

425 :param request: 

426 The PreparedReqest being sent over the connection. 

427 :type request: 

428 :class:`~requests.models.PreparedRequest` 

429 :param verify: 

430 Either a boolean, in which case it controls whether 

431 we verify the server's TLS certificate, or a string, in which case it 

432 must be a path to a CA bundle to use. 

433 :param cert: 

434 (optional) Any user-provided SSL certificate for client 

435 authentication (a.k.a., mTLS). This may be a string (i.e., just 

436 the path to a file which holds both certificate and key) or a 

437 tuple of length 2 with the certificate file path and key file 

438 path. 

439 :returns: 

440 A tuple of two dictionaries. The first is the "host parameters" 

441 portion of the Pool Key including scheme, hostname, and port. The 

442 second is a dictionary of SSLContext related parameters. 

443 """ 

444 return _urllib3_request_context(request, verify, cert, self.poolmanager) 

445 

446 def get_connection_with_tls_context(self, request, verify, proxies=None, cert=None): 

447 """Returns a urllib3 connection for the given request and TLS settings. 

448 This should not be called from user code, and is only exposed for use 

449 when subclassing the :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. 

450 

451 :param request: 

452 The :class:`PreparedRequest <PreparedRequest>` object to be sent 

453 over the connection. 

454 :param verify: 

455 Either a boolean, in which case it controls whether we verify the 

456 server's TLS certificate, or a string, in which case it must be a 

457 path to a CA bundle to use. 

458 :param proxies: 

459 (optional) The proxies dictionary to apply to the request. 

460 :param cert: 

461 (optional) Any user-provided SSL certificate to be used for client 

462 authentication (a.k.a., mTLS). 

463 :rtype: 

464 urllib3.ConnectionPool 

465 """ 

466 proxy = select_proxy(request.url, proxies) 

467 try: 

468 host_params, pool_kwargs = self.build_connection_pool_key_attributes( 

469 request, 

470 verify, 

471 cert, 

472 ) 

473 except ValueError as e: 

474 raise InvalidURL(e, request=request) 

475 if proxy: 

476 proxy = prepend_scheme_if_needed(proxy, "http") 

477 proxy_url = parse_url(proxy) 

478 if not proxy_url.host: 

479 raise InvalidProxyURL( 

480 "Please check proxy URL. It is malformed " 

481 "and could be missing the host." 

482 ) 

483 proxy_manager = self.proxy_manager_for(proxy) 

484 conn = proxy_manager.connection_from_host( 

485 **host_params, pool_kwargs=pool_kwargs 

486 ) 

487 else: 

488 # Only scheme should be lower case 

489 conn = self.poolmanager.connection_from_host( 

490 **host_params, pool_kwargs=pool_kwargs 

491 ) 

492 

493 return conn 

494 

495 def get_connection(self, url, proxies=None): 

496 """DEPRECATED: Users should move to `get_connection_with_tls_context` 

497 for all subclasses of HTTPAdapter using Requests>=2.32.2. 

498 

499 Returns a urllib3 connection for the given URL. This should not be 

500 called from user code, and is only exposed for use when subclassing the 

501 :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. 

502 

503 :param url: The URL to connect to. 

504 :param proxies: (optional) A Requests-style dictionary of proxies used on this request. 

505 :rtype: urllib3.ConnectionPool 

506 """ 

507 warnings.warn( 

508 ( 

509 "`get_connection` has been deprecated in favor of " 

510 "`get_connection_with_tls_context`. Custom HTTPAdapter subclasses " 

511 "will need to migrate for Requests>=2.32.2. Please see " 

512 "https://github.com/psf/requests/pull/6710 for more details." 

513 ), 

514 DeprecationWarning, 

515 ) 

516 proxy = select_proxy(url, proxies) 

517 

518 if proxy: 

519 proxy = prepend_scheme_if_needed(proxy, "http") 

520 proxy_url = parse_url(proxy) 

521 if not proxy_url.host: 

522 raise InvalidProxyURL( 

523 "Please check proxy URL. It is malformed " 

524 "and could be missing the host." 

525 ) 

526 proxy_manager = self.proxy_manager_for(proxy) 

527 conn = proxy_manager.connection_from_url(url) 

528 else: 

529 # Only scheme should be lower case 

530 parsed = urlparse(url) 

531 url = parsed.geturl() 

532 conn = self.poolmanager.connection_from_url(url) 

533 

534 return conn 

535 

536 def close(self): 

537 """Disposes of any internal state. 

538 

539 Currently, this closes the PoolManager and any active ProxyManager, 

540 which closes any pooled connections. 

541 """ 

542 self.poolmanager.clear() 

543 for proxy in self.proxy_manager.values(): 

544 proxy.clear() 

545 

546 def request_url(self, request, proxies): 

547 """Obtain the url to use when making the final request. 

548 

549 If the message is being sent through a HTTP proxy, the full URL has to 

550 be used. Otherwise, we should only use the path portion of the URL. 

551 

552 This should not be called from user code, and is only exposed for use 

553 when subclassing the 

554 :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. 

555 

556 :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. 

557 :param proxies: A dictionary of schemes or schemes and hosts to proxy URLs. 

558 :rtype: str 

559 """ 

560 proxy = select_proxy(request.url, proxies) 

561 scheme = urlparse(request.url).scheme 

562 

563 is_proxied_http_request = proxy and scheme != "https" 

564 using_socks_proxy = False 

565 if proxy: 

566 proxy_scheme = urlparse(proxy).scheme.lower() 

567 using_socks_proxy = proxy_scheme.startswith("socks") 

568 

569 url = request.path_url 

570 if url.startswith("//"): # Don't confuse urllib3 

571 url = f"/{url.lstrip('/')}" 

572 

573 if is_proxied_http_request and not using_socks_proxy: 

574 url = urldefragauth(request.url) 

575 

576 return url 

577 

578 def add_headers(self, request, **kwargs): 

579 """Add any headers needed by the connection. As of v2.0 this does 

580 nothing by default, but is left for overriding by users that subclass 

581 the :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. 

582 

583 This should not be called from user code, and is only exposed for use 

584 when subclassing the 

585 :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. 

586 

587 :param request: The :class:`PreparedRequest <PreparedRequest>` to add headers to. 

588 :param kwargs: The keyword arguments from the call to send(). 

589 """ 

590 pass 

591 

592 def proxy_headers(self, proxy): 

593 """Returns a dictionary of the headers to add to any request sent 

594 through a proxy. This works with urllib3 magic to ensure that they are 

595 correctly sent to the proxy, rather than in a tunnelled request if 

596 CONNECT is being used. 

597 

598 This should not be called from user code, and is only exposed for use 

599 when subclassing the 

600 :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. 

601 

602 :param proxy: The url of the proxy being used for this request. 

603 :rtype: dict 

604 """ 

605 headers = {} 

606 username, password = get_auth_from_url(proxy) 

607 

608 if username: 

609 headers["Proxy-Authorization"] = _basic_auth_str(username, password) 

610 

611 return headers 

612 

613 def send( 

614 self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None 

615 ): 

616 """Sends PreparedRequest object. Returns Response object. 

617 

618 :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. 

619 :param stream: (optional) Whether to stream the request content. 

620 :param timeout: (optional) How long to wait for the server to send 

621 data before giving up, as a float, or a :ref:`(connect timeout, 

622 read timeout) <timeouts>` tuple. 

623 :type timeout: float or tuple or urllib3 Timeout object 

624 :param verify: (optional) Either a boolean, in which case it controls whether 

625 we verify the server's TLS certificate, or a string, in which case it 

626 must be a path to a CA bundle to use 

627 :param cert: (optional) Any user-provided SSL certificate to be trusted. 

628 :param proxies: (optional) The proxies dictionary to apply to the request. 

629 :rtype: requests.Response 

630 """ 

631 

632 try: 

633 conn = self.get_connection_with_tls_context( 

634 request, verify, proxies=proxies, cert=cert 

635 ) 

636 except LocationValueError as e: 

637 raise InvalidURL(e, request=request) 

638 

639 self.cert_verify(conn, request.url, verify, cert) 

640 url = self.request_url(request, proxies) 

641 self.add_headers( 

642 request, 

643 stream=stream, 

644 timeout=timeout, 

645 verify=verify, 

646 cert=cert, 

647 proxies=proxies, 

648 ) 

649 

650 chunked = not (request.body is None or "Content-Length" in request.headers) 

651 

652 if isinstance(timeout, tuple): 

653 try: 

654 connect, read = timeout 

655 timeout = TimeoutSauce(connect=connect, read=read) 

656 except ValueError: 

657 raise ValueError( 

658 f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " 

659 f"or a single float to set both timeouts to the same value." 

660 ) 

661 elif isinstance(timeout, TimeoutSauce): 

662 pass 

663 else: 

664 timeout = TimeoutSauce(connect=timeout, read=timeout) 

665 

666 try: 

667 resp = conn.urlopen( 

668 method=request.method, 

669 url=url, 

670 body=request.body, 

671 headers=request.headers, 

672 redirect=False, 

673 assert_same_host=False, 

674 preload_content=False, 

675 decode_content=False, 

676 retries=self.max_retries, 

677 timeout=timeout, 

678 chunked=chunked, 

679 ) 

680 

681 except (ProtocolError, OSError) as err: 

682 raise ConnectionError(err, request=request) 

683 

684 except MaxRetryError as e: 

685 if isinstance(e.reason, ConnectTimeoutError): 

686 # TODO: Remove this in 3.0.0: see #2811 

687 if not isinstance(e.reason, NewConnectionError): 

688 raise ConnectTimeout(e, request=request) 

689 

690 if isinstance(e.reason, ResponseError): 

691 raise RetryError(e, request=request) 

692 

693 if isinstance(e.reason, _ProxyError): 

694 raise ProxyError(e, request=request) 

695 

696 if isinstance(e.reason, _SSLError): 

697 # This branch is for urllib3 v1.22 and later. 

698 raise SSLError(e, request=request) 

699 

700 raise ConnectionError(e, request=request) 

701 

702 except ClosedPoolError as e: 

703 raise ConnectionError(e, request=request) 

704 

705 except _ProxyError as e: 

706 raise ProxyError(e) 

707 

708 except (_SSLError, _HTTPError) as e: 

709 if isinstance(e, _SSLError): 

710 # This branch is for urllib3 versions earlier than v1.22 

711 raise SSLError(e, request=request) 

712 elif isinstance(e, ReadTimeoutError): 

713 raise ReadTimeout(e, request=request) 

714 elif isinstance(e, _InvalidHeader): 

715 raise InvalidHeader(e, request=request) 

716 else: 

717 raise 

718 

719 return self.build_response(request, resp)