-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
bpo-29654 : Support If-Modified-Since HTTP header (browser cache) #298
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
20cc898
f1d8a48
c4403ec
3225080
415e4af
8595735
2be2f8c
c3337f4
143e1e9
42edfe3
1e68be9
fc20596
9436e45
708ff03
6a58894
db46671
41f74ef
204c503
e2fee49
6dadf6e
c389bf6
3cc4f6d
294e164
6c5ba39
1e0f3e3
2503add
36a8e2a
c8b108f
bd91346
d3238d2
16f9e11
c669909
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
…as not modified
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -100,6 +100,7 @@ | |
import socketserver | ||
import sys | ||
import time | ||
import datetime | ||
import urllib.parse | ||
import copy | ||
import argparse | ||
|
@@ -687,6 +688,21 @@ def send_head(self): | |
self.send_error(HTTPStatus.NOT_FOUND, "File not found") | ||
return None | ||
try: | ||
# Use browser cache if possible | ||
if "If-Modified-Since" in self.headers: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The RFC https://tools.ietf.org/html/rfc7232#section-3.3 says you have to ignore this field if If-None-Match is also specified |
||
# compare If-Modified-Since and date of last file modification | ||
fs = os.stat(path) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe combine with the existing call below, too |
||
ims = email.utils.parsedate(self.headers["If-Modified-Since"]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This email function accepts a timezone (e.g. from the documentation: -0500), and seems to ignore it. But it may make more sense for a HTTP server to either adjust the date according to the timezone (e.g. add 5 hours), or treat it as an error (required by RFC 7232). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks a problem to me that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, the latest commit uses |
||
if ims is not None: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done in commit fc20596 |
||
ims_datetime = datetime.datetime(*ims[:7]) | ||
ims_dtstring = ims_datetime.strftime("%d %b %Y %H:%M:%S") | ||
last_modif = datetime.datetime.utcfromtimestamp( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
fs.st_mtime).strftime("%d %b %Y %H:%M:%S") | ||
if last_modif <= ims_dtstring: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why compare string representations rather than datetime objects or just tuples? The order of such strings is different from the order of datetime objects. |
||
self.send_response(HTTPStatus.NOT_MODIFIED) | ||
self.end_headers() | ||
f.close() | ||
return | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
self.send_response(HTTPStatus.OK) | ||
self.send_header("Content-type", ctype) | ||
fs = os.fstat(f.fileno()) | ||
|
@@ -1212,3 +1228,5 @@ def test(HandlerClass=BaseHTTPRequestHandler, | |
else: | ||
handler_class = SimpleHTTPRequestHandler | ||
test(HandlerClass=handler_class, port=args.port, bind=args.bind) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unrelated changes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't add this line. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done in commit fc20596 |
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -444,6 +444,20 @@ def test_head(self): | |
self.assertEqual(response.getheader('content-type'), | ||
'application/octet-stream') | ||
|
||
def test_browser_cache(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be better to split this test on few tests. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done in commit 42edfe3. |
||
#constructs the path relative to the root directory of the HTTPServer | ||
response = self.request(self.base_url + '/test') | ||
self.check_status_and_reason(response, HTTPStatus.OK, data=self.data) | ||
# get Last-Modified response heaer | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Spelling: header. But this comment seems redundant; isn’t the code obvious enough? |
||
last_modif = response.headers['Last-modified'] | ||
# send new request to the same url with request header | ||
# If-Modified-Since | ||
from email.message import Message | ||
headers = Message() | ||
headers['If-Modified-Since'] = last_modif | ||
response = self.request(self.base_url + '/test', headers=headers) | ||
self.check_status_and_reason(response, HTTPStatus.NOT_MODIFIED) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please repeat the test with an earlier date, verifying that a response body is returned. |
||
|
||
def test_invalid_requests(self): | ||
response = self.request('/', method='FOO') | ||
self.check_status_and_reason(response, HTTPStatus.NOT_IMPLEMENTED) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try to support alphabetical order of imports. I.e. add
import datetime
beforeimport email.utils
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in commit 708ff03. The order was not supported for argparse and copy...
I also changed to version to 0.7.