Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/urllib3/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
commit_id: COMMIT_ID
__commit_id__: COMMIT_ID

__version__ = version = '2.6.1'
__version_tuple__ = version_tuple = (2, 6, 1)
__version__ = version = '2.6.3'
__version_tuple__ = version_tuple = (2, 6, 3)

__commit_id__ = commit_id = None
1 change: 1 addition & 0 deletions lib/urllib3/contrib/emscripten/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ def inject_into_urllib3() -> None:
HTTPSConnectionPool.ConnectionCls = EmscriptenHTTPSConnection
urllib3.connection.HTTPConnection = EmscriptenHTTPConnection # type: ignore[misc,assignment]
urllib3.connection.HTTPSConnection = EmscriptenHTTPSConnection # type: ignore[misc,assignment]
urllib3.connection.VerifiedHTTPSConnection = EmscriptenHTTPSConnection # type: ignore[assignment]
1 change: 1 addition & 0 deletions lib/urllib3/contrib/emscripten/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class EmscriptenHTTPConnection:
is_verified: bool = False
proxy_is_verified: bool | None = None

response_class: type[BaseHTTPResponse] = EmscriptenHttpResponseWrapper
_response: EmscriptenResponse | None

def __init__(
Expand Down
6 changes: 3 additions & 3 deletions lib/urllib3/http2/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
import types
import typing

import h2.config # type: ignore[import-untyped]
import h2.connection # type: ignore[import-untyped]
import h2.events # type: ignore[import-untyped]
import h2.config
import h2.connection
import h2.events

from .._base_connection import _TYPE_BODY
from .._collections import HTTPHeaderDict
Expand Down
18 changes: 13 additions & 5 deletions lib/urllib3/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -797,7 +797,11 @@ def drain_conn(self) -> None:
Unread data in the HTTPResponse connection blocks the connection from being released back to the pool.
"""
try:
self.read()
self.read(
# Do not spend resources decoding the content unless
# decoding has already been initiated.
decode_content=self._has_decoded_content,
)
except (HTTPError, OSError, BaseSSLError, HTTPException):
pass

Expand Down Expand Up @@ -1407,10 +1411,14 @@ def read_chunked(
amt = None

while True:
self._update_chunk_length()
if self.chunk_left == 0:
break
chunk = self._handle_chunk(amt)
# First, check if any data is left in the decoder's buffer.
if self._decoder and self._decoder.has_unconsumed_tail:
chunk = b""
else:
self._update_chunk_length()
if self.chunk_left == 0:
break
chunk = self._handle_chunk(amt)
decoded = self._decode(
chunk,
decode_content=decode_content,
Expand Down
16 changes: 16 additions & 0 deletions lib/urllib3/util/retry.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ class Retry:
Sequence of headers to remove from the request when a response
indicating a redirect is returned before firing off the redirected
request.

:param int retry_after_max: Number of seconds to allow as the maximum for
Retry-After headers. Defaults to :attr:`Retry.DEFAULT_RETRY_AFTER_MAX`.
Any Retry-After headers larger than this value will be limited to this
value.
"""

#: Default methods to be used for ``allowed_methods``
Expand All @@ -196,6 +201,10 @@ class Retry:
#: Default maximum backoff time.
DEFAULT_BACKOFF_MAX = 120

# This is undocumented in the RFC. Setting to 6 hours matches other popular libraries.
#: Default maximum allowed value for Retry-After headers in seconds
DEFAULT_RETRY_AFTER_MAX: typing.Final[int] = 21600

# Backward compatibility; assigned outside of the class.
DEFAULT: typing.ClassVar[Retry]

Expand All @@ -219,6 +228,7 @@ def __init__(
str
] = DEFAULT_REMOVE_HEADERS_ON_REDIRECT,
backoff_jitter: float = 0.0,
retry_after_max: int = DEFAULT_RETRY_AFTER_MAX,
) -> None:
self.total = total
self.connect = connect
Expand All @@ -235,6 +245,7 @@ def __init__(
self.allowed_methods = allowed_methods
self.backoff_factor = backoff_factor
self.backoff_max = backoff_max
self.retry_after_max = retry_after_max
self.raise_on_redirect = raise_on_redirect
self.raise_on_status = raise_on_status
self.history = history or ()
Expand All @@ -256,6 +267,7 @@ def new(self, **kw: typing.Any) -> Self:
status_forcelist=self.status_forcelist,
backoff_factor=self.backoff_factor,
backoff_max=self.backoff_max,
retry_after_max=self.retry_after_max,
raise_on_redirect=self.raise_on_redirect,
raise_on_status=self.raise_on_status,
history=self.history,
Expand Down Expand Up @@ -320,6 +332,10 @@ def parse_retry_after(self, retry_after: str) -> float:

seconds = max(seconds, 0)

# Check the seconds do not exceed the specified maximum
if seconds > self.retry_after_max:
seconds = self.retry_after_max

return seconds

def get_retry_after(self, response: BaseHTTPResponse) -> float | None:
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ get_latest_version==2.0.0
idna==3.11
requests==2.32.5
semver==3.0.4
urllib3==2.6.1
urllib3==2.6.3