Same as :meth:`urllib3.HTTPConnectionPool.urlopen` with custom cross-host redirect logic and only sends the request-uri portion of the ``url``. The given ``url`` parameter must be absolute, such that an appropriate :class:`urllib3.connectionpool.ConnectionPo
( # type: ignore[override]
self, method: str, url: str, redirect: bool = True, **kw: typing.Any
)
| 421 | ) |
| 422 | |
| 423 | def urlopen( # type: ignore[override] |
| 424 | self, method: str, url: str, redirect: bool = True, **kw: typing.Any |
| 425 | ) -> BaseHTTPResponse: |
| 426 | """ |
| 427 | Same as :meth:`urllib3.HTTPConnectionPool.urlopen` |
| 428 | with custom cross-host redirect logic and only sends the request-uri |
| 429 | portion of the ``url``. |
| 430 | |
| 431 | The given ``url`` parameter must be absolute, such that an appropriate |
| 432 | :class:`urllib3.connectionpool.ConnectionPool` can be chosen for it. |
| 433 | """ |
| 434 | u = parse_url(url) |
| 435 | |
| 436 | if u.scheme is None: |
| 437 | warnings.warn( |
| 438 | "URLs without a scheme (ie 'https://') are deprecated and will raise an error " |
| 439 | "in urllib3 v3.0. To avoid this FutureWarning ensure all URLs " |
| 440 | "start with 'https://' or 'http://'. Read more in this issue: " |
| 441 | "https://github.com/urllib3/urllib3/issues/2920", |
| 442 | category=FutureWarning, |
| 443 | stacklevel=2, |
| 444 | ) |
| 445 | |
| 446 | conn = self.connection_from_host(u.host, port=u.port, scheme=u.scheme) |
| 447 | |
| 448 | kw["assert_same_host"] = False |
| 449 | kw["redirect"] = False |
| 450 | |
| 451 | if "headers" not in kw: |
| 452 | kw["headers"] = self.headers |
| 453 | |
| 454 | if self._proxy_requires_url_absolute_form(u): |
| 455 | response = conn.urlopen(method, url, **kw) |
| 456 | else: |
| 457 | response = conn.urlopen(method, u.request_uri, **kw) |
| 458 | |
| 459 | redirect_location = redirect and response.get_redirect_location() |
| 460 | if not redirect_location: |
| 461 | return response |
| 462 | |
| 463 | # Support relative URLs for redirecting. |
| 464 | redirect_location = urljoin(url, redirect_location) |
| 465 | |
| 466 | if response.status == 303: |
| 467 | # Change the method according to RFC 9110, Section 15.4.4. |
| 468 | method = "GET" |
| 469 | # And lose the body not to transfer anything sensitive. |
| 470 | kw["body"] = None |
| 471 | kw["headers"] = HTTPHeaderDict(kw["headers"])._prepare_for_method_change() |
| 472 | |
| 473 | retries = kw.get("retries", response.retries) |
| 474 | if not isinstance(retries, Retry): |
| 475 | retries = Retry.from_int(retries, redirect=redirect) |
| 476 | |
| 477 | # Strip headers marked as unsafe to forward to the redirected location. |
| 478 | # Check remove_headers_on_redirect to avoid a potential network call within |
| 479 | # conn.is_same_host() which may use socket.gethostbyname() in the future. |
| 480 | if retries.remove_headers_on_redirect and not conn.is_same_host( |