]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Parse if-modified-since timestamps without going through time_t or local time.
authorBen Darnell <ben@bendarnell.com>
Sat, 13 Apr 2013 22:15:49 +0000 (18:15 -0400)
committerBen Darnell <ben@bendarnell.com>
Sat, 13 Apr 2013 22:15:49 +0000 (18:15 -0400)
This fixes a bug on windows in which mktime cannot work with times before
the epoch.

Closes #713.

tornado/test/web_test.py
tornado/web.py

index 17a6c67c86abe58cb1be498673359c55f823b122..e1d71fb36dec6b4943b7bac7b7e57a18551a8004 100644 (file)
@@ -1,6 +1,7 @@
 from __future__ import absolute_import, division, print_function, with_statement
 from tornado import gen
 from tornado.escape import json_decode, utf8, to_unicode, recursive_unicode, native_str, to_basestring
+from tornado.httputil import format_timestamp
 from tornado.iostream import IOStream
 from tornado.log import app_log, gen_log
 from tornado.simple_httpclient import SimpleAsyncHTTPClient
@@ -813,6 +814,29 @@ class StaticFileTest(WebTestCase):
             'If-None-Match': response1.headers['Etag']})
         self.assertEqual(response2.code, 304)
 
+    def test_static_if_modified_since_pre_epoch(self):
+        # On windows, the functions that work with time_t do not accept
+        # negative values, and at least one client (processing.js) seems
+        # to use if-modified-since 1/1/1960 as a cache-busting technique.
+        response = self.fetch("/static/robots.txt", headers={
+                'If-Modified-Since': 'Fri, 01 Jan 1960 00:00:00 GMT'})
+        self.assertEqual(response.code, 200)
+
+    def test_static_if_modified_since_time_zone(self):
+        # Instead of the value from Last-Modified, make requests with times
+        # chosen just before and after the known modification time
+        # of the file to ensure that the right time zone is being used
+        # when parsing If-Modified-Since.
+        stat = os.stat(os.path.join(os.path.dirname(__file__),
+                                    'static/robots.txt'))
+
+        response = self.fetch('/static/robots.txt', headers={
+                'If-Modified-Since': format_timestamp(stat.st_mtime - 1)})
+        self.assertEqual(response.code, 200)
+        response = self.fetch('/static/robots.txt', headers={
+                'If-Modified-Since': format_timestamp(stat.st_mtime + 1)})
+        self.assertEqual(response.code, 304)
+
 
 @wsgi_safe
 class CustomStaticFileTest(WebTestCase):
index 3293b539e3d565567b06307d2fed8be0f93898b1..057536e94fb7f3c0365f085b91cacee0fbed55d2 100644 (file)
@@ -1638,7 +1638,7 @@ class StaticFileHandler(RequestHandler):
             raise HTTPError(403, "%s is not a file", path)
 
         stat_result = os.stat(abspath)
-        modified = datetime.datetime.fromtimestamp(stat_result[stat.ST_MTIME])
+        modified = datetime.datetime.utcfromtimestamp(stat_result[stat.ST_MTIME])
 
         self.set_header("Last-Modified", modified)
 
@@ -1660,7 +1660,7 @@ class StaticFileHandler(RequestHandler):
         ims_value = self.request.headers.get("If-Modified-Since")
         if ims_value is not None:
             date_tuple = email.utils.parsedate(ims_value)
-            if_since = datetime.datetime.fromtimestamp(time.mktime(date_tuple))
+            if_since = datetime.datetime(*date_tuple[:6])
             if if_since >= modified:
                 self.set_status(304)
                 return