Comments
Patch
@@ -212,6 +212,27 @@ def staticfile(directory, fname, req, im
if hash != immutablehash:
raise ErrorResponse(HTTP_NOT_FOUND)
+ # Hash matches and content is immutable. Do content-based caching.
+
+ # Strip ETag header added by common dispatch code, as it is
+ # using a weak validator (mtime) and isn't as robust as content
+ # hashing.
+ req.headers = [t for t in req.headers if t[0].lower() != 'etag']
+
+ # Conditional HTTP request for this hash. Avoid sending response
+ # body. This likely occurs only after a manual browser refresh,
+ # as clients shouldn't request URLs they've already cached
+ # otherwise.
+ if req.env.get('HTTP_IF_NONE_MATCH') == '"%s"' % hash:
+ raise ErrorResponse(HTTP_NOT_MODIFIED)
+
+ # Set ETag with strong validator (content hash). This allows
+ # refresh requests to be conditional.
+ req.headers.append(('ETag', '"%s"' % hash))
+
+ # Cache unconditionally for 1 year.
+ req.headers.append(('Cache-Control', 'max-age=31536000'))
+
req.respond(HTTP_OK, ct, body=data)
except TypeError:
raise ErrorResponse(HTTP_SERVER_ERROR, 'illegal filename')
@@ -236,6 +236,21 @@ staticimmutable with a bogus hash should
[1]
+staticimmutable for a valid hash should issue Cache-Control and content-based ETag header
+
+ $ get-with-headers.py --headeronly localhost:$HGPORT 'staticimmutable/e8690644d0bb4d35db4a08e469905a0c5ce363b7/hglogo.png' etag cache-control
+ 200 Script output follows
+ etag: "e8690644d0bb4d35db4a08e469905a0c5ce363b7"
+ cache-control: max-age=31536000
+
+and If-None-Match should result in 304
+
+ $ get-with-headers.py --twice --headeronly localhost:$HGPORT 'staticimmutable/e8690644d0bb4d35db4a08e469905a0c5ce363b7/hglogo.png' etag cache-control
+ 200 Script output follows
+ etag: "e8690644d0bb4d35db4a08e469905a0c5ce363b7"
+ cache-control: max-age=31536000
+ 304 Not Modified
+
should give a 404 - bad revision
$ get-with-headers.py localhost:$HGPORT 'file/spam/foo?style=raw'
@@ -461,7 +476,7 @@ stop and restart
Test the access/error files are opened in append mode
$ $PYTHON -c "print len(file('access.log').readlines()), 'log lines written'"
- 16 log lines written
+ 19 log lines written
static file