]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Cache the computed absolute path to the requested resource in 476/head
authorBirk Nilson <me@birknilson.se>
Mon, 26 Mar 2012 10:02:13 +0000 (12:02 +0200)
committerBirk Nilson <me@birknilson.se>
Mon, 26 Mar 2012 10:02:13 +0000 (12:02 +0200)
StaticFileHandler. The cache is cleared on_finish of each request
in order to ensure recomputation on each request.

tornado/web.py

index 2e490580589351e746e58a389940551b6d5197bc..20c382d5a96e8ce9ead72cd531b476dd40da3432 100644 (file)
@@ -1489,11 +1489,10 @@ class StaticFileHandler(RequestHandler):
 
     def get(self, path, include_body=True):
         path = self.parse_url_path(path)
-        abspath = self.get_absolute_path(path)
-        if not self.set_headers(abspath, path):
+        if not self.set_headers(path):
             return
 
-        body = self.get_content(abspath)
+        body = self.get_content(path)
         if not body:
             return
 
@@ -1506,6 +1505,13 @@ class StaticFileHandler(RequestHandler):
             assert self.request.method == "HEAD"
             self.set_header("Content-Length", len(body))
 
+    def on_finish(self):
+        # Cleanup the cached computation of the absolute path associated with
+        # the requested resource. This is crucial in order to ensure accurate
+        # responses in upcoming requests which would otherwise utilize the same
+        # absolute path as the initial one - which would be chaotic.
+        self._abspath = None
+
     def get_absolute_path(self, path):
         """Retrieve the absolute path on the filesystem where the resource
         corresponding to the given URL ``path`` can be found.
@@ -1513,6 +1519,13 @@ class StaticFileHandler(RequestHandler):
         This method also handles the validation of the given path and ensures
         resources outside of the static directory cannot be accessed.
         """
+        # In case the ``_abspath`` attribute exists and contains a value
+        # other than None the abspath has already been computed and verified.
+        # It can be returned instantly in order to avoid recomputation.
+        abspath = getattr(self, '_abspath', None)
+        if abspath is not None:
+            return abspath
+
         abspath = os.path.abspath(os.path.join(self.root, path))
         # os.path.abspath strips a trailing /
         # it needs to be temporarily added back for requests to root/
@@ -1530,13 +1543,16 @@ class StaticFileHandler(RequestHandler):
             raise HTTPError(404)
         if not os.path.isfile(abspath):
             raise HTTPError(403, "%s is not a file", path)
+
+        self._abspath = abspath
         return abspath
 
-    def set_headers(self, abspath, path):
+    def set_headers(self, path):
         """Set the response headers in order to ensure that client browsers
         will cache the requested resource and not proceed to retrieve its content
         in the case of a 304 response.
         """
+        abspath = self.get_absolute_path(path)
         stat_result = os.stat(abspath)
         modified = datetime.datetime.fromtimestamp(stat_result[stat.ST_MTIME])
 
@@ -1569,10 +1585,11 @@ class StaticFileHandler(RequestHandler):
 
         return True
 
-    def get_content(self, abspath):
+    def get_content(self, path):
         """Retrieve the content of the requested resource which is located
-        at the given ``abspath``.
+        at the given absolute ``path``.
         """
+        abspath = self.get_absolute_path(path)
         with open(abspath, "rb") as file:
             return file.read()
         return None