bpo-29654 : Support If-Modified-Since HTTP header (browser cache) (#298)

Return 304 response if file was not modified.
This commit is contained in:
Pierre Quentel 2017-04-02 12:26:12 +02:00 committed by Serhiy Storchaka
parent efbd4ea65d
commit 351adda54b
5 changed files with 112 additions and 9 deletions

View file

@ -14,11 +14,14 @@
import base64
import ntpath
import shutil
import urllib.parse
import email.message
import email.utils
import html
import http.client
import urllib.parse
import tempfile
import time
import datetime
from io import BytesIO
import unittest
@ -333,6 +336,13 @@ def setUp(self):
self.base_url = '/' + self.tempdir_name
with open(os.path.join(self.tempdir, 'test'), 'wb') as temp:
temp.write(self.data)
mtime = os.fstat(temp.fileno()).st_mtime
# compute last modification datetime for browser cache tests
last_modif = datetime.datetime.fromtimestamp(mtime,
datetime.timezone.utc)
self.last_modif_datetime = last_modif.replace(microsecond=0)
self.last_modif_header = email.utils.formatdate(
last_modif.timestamp(), usegmt=True)
def tearDown(self):
try:
@ -444,6 +454,44 @@ def test_head(self):
self.assertEqual(response.getheader('content-type'),
'application/octet-stream')
def test_browser_cache(self):
"""Check that when a request to /test is sent with the request header
If-Modified-Since set to date of last modification, the server returns
status code 304, not 200
"""
headers = email.message.Message()
headers['If-Modified-Since'] = self.last_modif_header
response = self.request(self.base_url + '/test', headers=headers)
self.check_status_and_reason(response, HTTPStatus.NOT_MODIFIED)
# one hour after last modification : must return 304
new_dt = self.last_modif_datetime + datetime.timedelta(hours=1)
headers = email.message.Message()
headers['If-Modified-Since'] = email.utils.format_datetime(new_dt,
usegmt=True)
response = self.request(self.base_url + '/test', headers=headers)
self.check_status_and_reason(response, HTTPStatus.NOT_MODIFIED)
def test_browser_cache_file_changed(self):
# with If-Modified-Since earlier than Last-Modified, must return 200
dt = self.last_modif_datetime
# build datetime object : 365 days before last modification
old_dt = dt - datetime.timedelta(days=365)
headers = email.message.Message()
headers['If-Modified-Since'] = email.utils.format_datetime(old_dt,
usegmt=True)
response = self.request(self.base_url + '/test', headers=headers)
self.check_status_and_reason(response, HTTPStatus.OK)
def test_browser_cache_with_If_None_Match_header(self):
# if If-None-Match header is present, ignore If-Modified-Since
headers = email.message.Message()
headers['If-Modified-Since'] = self.last_modif_header
headers['If-None-Match'] = "*"
response = self.request(self.base_url + '/test', headers=headers)
self.check_status_and_reason(response, HTTPStatus.OK)
def test_invalid_requests(self):
response = self.request('/', method='FOO')
self.check_status_and_reason(response, HTTPStatus.NOT_IMPLEMENTED)
@ -453,6 +501,15 @@ def test_invalid_requests(self):
response = self.request('/', method='GETs')
self.check_status_and_reason(response, HTTPStatus.NOT_IMPLEMENTED)
def test_last_modified(self):
"""Checks that the datetime returned in Last-Modified response header
is the actual datetime of last modification, rounded to the second
"""
response = self.request(self.base_url + '/test')
self.check_status_and_reason(response, HTTPStatus.OK, data=self.data)
last_modif_header = response.headers['Last-modified']
self.assertEqual(last_modif_header, self.last_modif_header)
def test_path_without_leading_slash(self):
response = self.request(self.tempdir_name + '/test')
self.check_status_and_reason(response, HTTPStatus.OK, data=self.data)