views.static.serve does not work with if-modified-since header the third time a file is requested
|Reported by:||Rob van der Linde||Owned by:||nobody|
|Has patch:||no||Needs documentation:||no|
|Needs tests:||no||Patch needs improvement:||no|
This is a very strange bug, but I will try to explain. I have a static file that has a 2006 last-modified date on it. The first time this file is requested through django.views.static.serve, the browser will download the file fully and send a last-modified header with it, properly dating to 2006. The second time this file is requested, the browser will send an if-modified-since request and the serve function detects this and only sends a HttpResponseNotModified so the browser won't re-download the file (this is fine so far and what I would expect). The problem is when I try to request the file for a third time, it will re-download the file, although it shouldn't (this is with Firefox 3 at least). I had a look with the web developer extension in Firefox and have found that the first time the file is sent, the last-modified date is 2006, but the third time the last-modified date is 2009. In fact, it is the date of the last request... not the date of the file... this is why it appears to be re-downloading the file the third time when it shouldn't.
I was able to fix this, by changing this part in /django/views/static.py (serve function, line 192):
if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'), statobj[stat.ST_MTIME], statobj[stat.ST_SIZE]): return HttpResponseNotModified()
if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'), statobj[stat.ST_MTIME], statobj[stat.ST_SIZE]): response = HttpResponseNotModified() response["Last-Modified"] = http_date(statobj[stat.ST_MTIME]) return response
By sending the last-modified date of the file again with the HttpResponseNotModified response, the third time I request the file, it won't re-download the file again in Firefox and display the proper 2006 date in web developer extension, instead of 2009, effectively fixing the problem. I don't know if this is a bug with Firefox or Django, however the small change to the code does fix it for me.