diff options
| author | Jon Bergli Heier <snakebite@jvnv.net> | 2011-07-18 16:27:25 +0200 | 
|---|---|---|
| committer | Jon Bergli Heier <snakebite@jvnv.net> | 2011-07-18 16:27:25 +0200 | 
| commit | e79bc33a0a1c58c96d5c42e537df6eb1fad56fd9 (patch) | |
| tree | 15807dc5c565faac23ab658f8380e1ee9de69f64 | |
| parent | fc81bb2bace6209f384db2f18500f61a0fa6870c (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-x | fbin.py | 42 | 
1 files changed, 25 insertions, 17 deletions
@@ -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  | 
