From e79bc33a0a1c58c96d5c42e537df6eb1fad56fd9 Mon Sep 17 00:00:00 2001 From: Jon Bergli Heier Date: Mon, 18 Jul 2011 16:27:25 +0200 Subject: Implemented simple cache control for files and thumbnails. Send the Last-Modified header, and react accordingly when receiving an If-Modified-Since header. --- fbin.py | 42 +++++++++++++++++++++++++----------------- 1 file 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 ['

Not Found

The file you requested does not exist.

'] - 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 -- cgit v1.2.3