summaryrefslogtreecommitdiff
path: root/Lib/http/server.py
diff options
context:
space:
mode:
authorPierre Quentel <pierre.quentel@gmail.com>2017-04-02 12:26:12 +0200
committerSerhiy Storchaka <storchaka@gmail.com>2017-04-02 13:26:12 +0300
commit351adda54bed3afbbf6db7725699679e68722d7d (patch)
treecde5d5563d5fc31730378a164ea0b73d0d67ff35 /Lib/http/server.py
parentefbd4ea65dbb9f87b1afeec6a760802756badee5 (diff)
downloadcpython-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.py39
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: