diff options
| author | Adrian Holovaty <adrian@holovaty.com> | 2006-03-03 04:53:04 +0000 |
|---|---|---|
| committer | Adrian Holovaty <adrian@holovaty.com> | 2006-03-03 04:53:04 +0000 |
| commit | 5beb39b896d581940ad3681229e87575aa83174d (patch) | |
| tree | d28b0e93108936d12cf4e37a26a36f377e1ed638 | |
| parent | cffd184daf070e5a1ce03d77cab55e0adebb90f8 (diff) | |
Fixed #1457 -- Added support for if-modified-since header in django.views.static. Thanks, Shannon -jj Behrens
git-svn-id: http://code.djangoproject.com/svn/django/trunk@2476 bcc190cf-cafb-0310-a4f2-bffc1f526a37
| -rw-r--r-- | AUTHORS | 1 | ||||
| -rw-r--r-- | django/views/static.py | 54 |
2 files changed, 48 insertions, 7 deletions
@@ -37,6 +37,7 @@ answer newbie questions, and generally made Django that much better: Arthur <avandorp@gmail.com> Jiri Barton Ned Batchelder <http://www.nedbatchelder.com/> + Shannon -jj Behrens <http://jjinux.blogspot.com/> James Bennett Paul Bissex <http://e-scribe.com/> Simon Blanchard diff --git a/django/views/static.py b/django/views/static.py index 536720f5e8..1499dd4847 100644 --- a/django/views/static.py +++ b/django/views/static.py @@ -2,9 +2,13 @@ import os import urllib import posixpath import mimetypes +import re +import rfc822 +import stat from django.core import template_loader from django.core.exceptions import Http404, ImproperlyConfigured -from django.utils.httpwrappers import HttpResponse, HttpResponseRedirect +from django.utils.httpwrappers import HttpResponse, HttpResponseRedirect, \ + HttpResponseNotModified from django.core.template import Template, Context, TemplateDoesNotExist def serve(request, path, document_root=None, show_indexes=False): @@ -41,13 +45,19 @@ def serve(request, path, document_root=None, show_indexes=False): if os.path.isdir(fullpath): if show_indexes: return directory_index(newpath, fullpath) - else: - raise Http404, "Directory indexes are not allowed here." - elif not os.path.exists(fullpath): + raise Http404, "Directory indexes are not allowed here." + if not os.path.exists(fullpath): raise Http404, '"%s" does not exist' % fullpath - else: - mimetype = mimetypes.guess_type(fullpath)[0] - return HttpResponse(open(fullpath, 'rb').read(), mimetype=mimetype) + # Respect the If-Modified-Since header. + statobj = os.stat(fullpath) + if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'), + statobj[stat.ST_MTIME], statobj[stat.ST_SIZE]): + return HttpResponseNotModified() + mimetype = mimetypes.guess_type(fullpath)[0] + contents = open(fullpath, 'rb').read() + response = HttpResponse(contents, mimetype=mimetype) + response["Last-Modified"] = rfc822.formatdate(statobj[stat.ST_MTIME]) + return response DEFAULT_DIRECTORY_INDEX_TEMPLATE = """ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> @@ -85,3 +95,33 @@ def directory_index(path, fullpath): 'file_list' : files, }) return HttpResponse(t.render(c)) + +def was_modified_since(header=None, mtime=0, size=0): + """ + Was something modified since the user last downloaded it? + + header + This is the value of the If-Modified-Since header. If this is None, + I'll just return True. + + mtime + This is the modification time of the item we're talking about. + + size + This is the size of the item we're talking about. + """ + try: + if header is None: + raise ValueError + matches = re.match(r"^([^;]+)(; length=([0-9]+))?$", header, + re.IGNORECASE) + header_mtime = rfc822.mktime_tz(rfc822.parsedate_tz( + matches.group(1))) + header_len = matches.group(3) + if header_len and int(header_len) != size: + raise ValueError + if mtime > header_mtime: + raise ValueError + except (AttributeError, ValueError): + return True + return False |
