Fix comparison from wrong formats with datetime objects (#2697)

Co-authored-by: Adam Hopkins <adam@amhopkins.com>
This commit is contained in:
stricaud 2023-03-20 11:12:09 +01:00 committed by GitHub
parent 8f265b8169
commit 009954003c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 75 additions and 1 deletions

View File

@ -148,7 +148,26 @@ async def validate_file(
last_modified = datetime.fromtimestamp( last_modified = datetime.fromtimestamp(
float(last_modified), tz=timezone.utc float(last_modified), tz=timezone.utc
).replace(microsecond=0) ).replace(microsecond=0)
if last_modified <= if_modified_since:
if (
last_modified.utcoffset() is None
and if_modified_since.utcoffset() is not None
):
logger.warning(
"Cannot compare tz-aware and tz-naive datetimes. To avoid "
"this conflict Sanic is converting last_modified to UTC."
)
last_modified.replace(tzinfo=timezone.utc)
elif (
last_modified.utcoffset() is not None
and if_modified_since.utcoffset() is None
):
logger.warning(
"Cannot compare tz-aware and tz-naive datetimes. To avoid "
"this conflict Sanic is converting if_modified_since to UTC."
)
if_modified_since.replace(tzinfo=timezone.utc)
if last_modified.timestamp() <= if_modified_since.timestamp():
return HTTPResponse(status=304) return HTTPResponse(status=304)

View File

@ -0,0 +1,55 @@
from datetime import datetime, timezone
from logging import INFO
import pytest
from sanic.compat import Header
from sanic.response.convenience import validate_file
@pytest.mark.parametrize(
"ifmod,lastmod,expected",
(
("Sat, 01 Apr 2023 00:00:00 GMT", 1672524000, None),
(
"Sat, 01 Apr 2023 00:00:00",
1672524000,
"converting if_modified_since",
),
(
"Sat, 01 Apr 2023 00:00:00 GMT",
datetime(2023, 1, 1, 0, 0, 0),
"converting last_modified",
),
(
"Sat, 01 Apr 2023 00:00:00",
datetime(2023, 1, 1, 0, 0, 0),
None,
),
(
"Sat, 01 Apr 2023 00:00:00 GMT",
datetime(2023, 1, 1, 0, 0, 0).replace(tzinfo=timezone.utc),
None,
),
(
"Sat, 01 Apr 2023 00:00:00",
datetime(2023, 1, 1, 0, 0, 0).replace(tzinfo=timezone.utc),
"converting if_modified_since",
),
),
)
@pytest.mark.asyncio
async def test_file_timestamp_validation(
lastmod, ifmod, expected, caplog: pytest.LogCaptureFixture
):
headers = Header([["If-Modified-Since", ifmod]])
with caplog.at_level(INFO):
response = await validate_file(headers, lastmod)
assert response.status == 304
records = caplog.records
if not expected:
assert len(records) == 0
else:
record = records[0]
assert expected in record.message