summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Bergli Heier <snakebite@jvnv.net>2011-07-18 16:27:25 +0200
committerJon Bergli Heier <snakebite@jvnv.net>2011-07-18 16:27:25 +0200
commite79bc33a0a1c58c96d5c42e537df6eb1fad56fd9 (patch)
tree15807dc5c565faac23ab658f8380e1ee9de69f64
parentfc81bb2bace6209f384db2f18500f61a0fa6870c (diff)
Implemented simple cache control for files and thumbnails.
Send the Last-Modified header, and react accordingly when receiving an If-Modified-Since header.
-rwxr-xr-xfbin.py42
1 files changed, 25 insertions, 17 deletions
diff --git a/fbin.py b/fbin.py
index 2689f47..0a5f578 100755
--- a/fbin.py
+++ b/fbin.py
@@ -5,6 +5,7 @@ import settings, db, os, random, datetime, shutil, mimetypes, cgi, tempfile, has
from PIL import Image
base62_alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+rfc1123_format = '%a, %d %b %Y %H:%M:%S +0000'
if not os.path.isdir(settings.file_directory):
os.mkdir(settings.file_directory)
@@ -55,17 +56,6 @@ class Application(object):
return user
- def get_file_path(self, hash):
- session = db.Session()
- try:
- file = session.query(db.File).filter(db.File.hash == hash).one()
- except db.NoResultFound:
- return None
- finally:
- session.close()
-
- return os.path.join(settings.file_directory, hash + os.path.splitext(file.filename)[1])
-
def add_file(self, path, filename, file_hash, user = None):
hash = ''.join(random.choice(base62_alphabet) for x in xrange(5))
new_path = os.path.join(settings.file_directory, hash + os.path.splitext(filename)[1])
@@ -122,18 +112,31 @@ class Application(object):
finally:
session.close()
+ def not_modified(self, environ, date):
+ if not 'HTTP_IF_MODIFIED_SINCE' in environ:
+ return False
+ mod_since_date = datetime.datetime.strptime(environ['HTTP_IF_MODIFIED_SINCE'], rfc1123_format)
+ return date == mod_since_date
+
def file(self, environ, start_response, path):
hash = path[1]
if '.' in hash:
hash = hash.split('.')[0]
- filename = self.get_file_path(hash)
+ file = self.get_file_by_file_hash(hash)
+ filename = file.get_path()
if filename == None:
start_response('404 Not Found', [('Content-Type', 'text/html')])
return ['<h1>Not Found</h1><p>The file you requested does not exist.</p>']
- mime = mimetypes.guess_type(filename, strict = False)[0] or 'application/octet-stream'
+ # strip microseconds
+ if self.not_modified(environ, file.date - datetime.timedelta(microseconds = file.date.microsecond)):
+ start_response('304 Not Modified', [('Last-Modified', file.date.strftime(rfc1123_format))])
+ return []
- start_response('200 OK', [('Content-Type', mime), ('Content-Length', str(os.path.getsize(filename)))])
+ mime = mimetypes.guess_type(file.filename, strict = False)[0] or 'application/octet-stream'
+
+ start_response('200 OK', [('Content-Type', mime), ('Content-Length', str(os.path.getsize(filename))),
+ ('Last-Modified', file.date.strftime(rfc1123_format))])
return open(filename, 'rb')
def upload(self, environ, start_response, path):
@@ -308,12 +311,17 @@ class Application(object):
hash = path[1]
thumbfile = os.path.join(settings.thumb_directory, hash + '.jpg')
if not os.access(thumbfile, os.F_OK):
- filename = self.get_file_path(hash)
- im = Image.open(filename)
+ file = self.get_file_by_file_hash(hash)
+ im = Image.open(file.get_path())
im.thumbnail(settings.thumb_size, Image.ANTIALIAS)
im.save(thumbfile)
- start_response('200 OK', [('Content-Type', 'image/jpeg')])
+ date = datetime.datetime.utcfromtimestamp(os.path.getmtime(thumbfile))
+ if self.not_modified(environ, date):
+ start_response('304 Not Modified', [('Last-Modified', date.strftime(rfc1123_format))])
+ return []
+
+ start_response('200 OK', [('Content-Type', 'image/jpeg'), ('Last-Modified', date.strftime(rfc1123_format))])
return open(thumbfile, 'rb')
f = file