Skip to content

Commit

Permalink
Use tz-aware functions in Retry.parse_retry_after()
Browse files Browse the repository at this point in the history
  • Loading branch information
sethmlarson committed Aug 24, 2020
1 parent 2bd2893 commit 9ff9bf7
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 15 deletions.
1 change: 1 addition & 0 deletions dev-requirements.txt
Expand Up @@ -7,6 +7,7 @@ PySocks==1.7.1
win-inet-pton==1.1.0
pytest==4.6.9
pytest-timeout==1.3.4
pytest-freezegun==0.3.0.post1
flaky==3.6.1
trustme==0.5.3
cryptography==2.8
Expand Down
4 changes: 2 additions & 2 deletions src/urllib3/util/retry.py
Expand Up @@ -266,10 +266,10 @@ def parse_retry_after(self, retry_after):
if re.match(r"^\s*[0-9]+\s*$", retry_after):
seconds = int(retry_after)
else:
retry_date_tuple = email.utils.parsedate(retry_after)
retry_date_tuple = email.utils.parsedate_tz(retry_after)
if retry_date_tuple is None:
raise InvalidHeader("Invalid Retry-After header: %s" % retry_after)
retry_date = time.mktime(retry_date_tuple)
retry_date = email.utils.mktime_tz(retry_date_tuple)
seconds = retry_date - time.time()

if seconds < 0:
Expand Down
20 changes: 7 additions & 13 deletions test/test_retry.py
@@ -1,7 +1,5 @@
import datetime
import mock
import pytest
import time

from urllib3.response import HTTPResponse
from urllib3.packages import six
Expand Down Expand Up @@ -313,6 +311,7 @@ def test_respect_retry_after_header_propagated(self, respect_retry_after_header)
new_retry = retry.new()
assert new_retry.respect_retry_after_header == respect_retry_after_header

@pytest.mark.freeze_time("2019-06-03 11:00:00", tz_offset=0)
@pytest.mark.parametrize(
"retry_after_header,respect_retry_after_header,sleep_duration",
[
Expand All @@ -326,24 +325,19 @@ def test_respect_retry_after_header_propagated(self, respect_retry_after_header)
("Mon, 3 Jun 2019 11:00:00 UTC", True, None),
# Won't sleep due to current time reached + not respecting header
("Mon, 3 Jun 2019 11:00:00 UTC", False, None),
# Handle all the formats in RFC 7231 Section 7.1.1.1
("Mon, 03 Jun 2019 11:30:12 GMT", True, 1812),
("Monday, 03-Jun-19 11:30:12 GMT", True, 1812),
# Assume that datetimes without a timezone are in UTC per RFC 7231
("Mon Jun 3 11:30:12 2019", True, 1812),
],
)
def test_respect_retry_after_header_sleep(
self, retry_after_header, respect_retry_after_header, sleep_duration
):
retry = Retry(respect_retry_after_header=respect_retry_after_header)

# Date header syntax can specify an absolute date; compare this to the
# time in the parametrized inputs above.
current_time = mock.MagicMock(
return_value=time.mktime(
datetime.datetime(year=2019, month=6, day=3, hour=11).timetuple()
)
)

with mock.patch("time.sleep") as sleep_mock, mock.patch(
"time.time", current_time
):
with mock.patch("time.sleep") as sleep_mock:
# for the default behavior, it must be in RETRY_AFTER_STATUS_CODES
response = HTTPResponse(
status=503, headers={"Retry-After": retry_after_header}
Expand Down

0 comments on commit 9ff9bf7

Please sign in to comment.