diff options
author | Pierre Quentel <pierre.quentel@gmail.com> | 2017-04-02 12:26:12 +0200 |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2017-04-02 13:26:12 +0300 |
commit | 351adda54bed3afbbf6db7725699679e68722d7d (patch) | |
tree | cde5d5563d5fc31730378a164ea0b73d0d67ff35 /Lib/http/server.py | |
parent | efbd4ea65dbb9f87b1afeec6a760802756badee5 (diff) | |
download | cpython-git-351adda54bed3afbbf6db7725699679e68722d7d.tar.gz |
bpo-29654 : Support If-Modified-Since HTTP header (browser cache) (#298)
Return 304 response if file was not modified.
Diffstat (limited to 'Lib/http/server.py')
-rw-r--r-- | Lib/http/server.py | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/Lib/http/server.py b/Lib/http/server.py index 61ddecc7ef..429490b73a 100644 --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -87,6 +87,9 @@ __all__ = [ "SimpleHTTPRequestHandler", "CGIHTTPRequestHandler", ] +import argparse +import copy +import datetime import email.utils import html import http.client @@ -101,8 +104,6 @@ import socketserver import sys import time import urllib.parse -import copy -import argparse from http import HTTPStatus @@ -686,12 +687,42 @@ class SimpleHTTPRequestHandler(BaseHTTPRequestHandler): except OSError: self.send_error(HTTPStatus.NOT_FOUND, "File not found") return None + try: + fs = os.fstat(f.fileno()) + # Use browser cache if possible + if ("If-Modified-Since" in self.headers + and "If-None-Match" not in self.headers): + # compare If-Modified-Since and time of last file modification + try: + ims = email.utils.parsedate_to_datetime( + self.headers["If-Modified-Since"]) + except (TypeError, IndexError, OverflowError, ValueError): + # ignore ill-formed values + pass + else: + if ims.tzinfo is None: + # obsolete format with no timezone, cf. + # https://tools.ietf.org/html/rfc7231#section-7.1.1.1 + ims = ims.replace(tzinfo=datetime.timezone.utc) + if ims.tzinfo is datetime.timezone.utc: + # compare to UTC datetime of last modification + last_modif = datetime.datetime.fromtimestamp( + fs.st_mtime, datetime.timezone.utc) + # remove microseconds, like in If-Modified-Since + last_modif = last_modif.replace(microsecond=0) + + if last_modif <= ims: + self.send_response(HTTPStatus.NOT_MODIFIED) + self.end_headers() + f.close() + return None + self.send_response(HTTPStatus.OK) self.send_header("Content-type", ctype) - fs = os.fstat(f.fileno()) self.send_header("Content-Length", str(fs[6])) - self.send_header("Last-Modified", self.date_time_string(fs.st_mtime)) + self.send_header("Last-Modified", + self.date_time_string(fs.st_mtime)) self.end_headers() return f except: |