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

@ -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: