summaryrefslogtreecommitdiff
path: root/paste/fileapp.py
diff options
context:
space:
mode:
authorcce <devnull@localhost>2005-12-22 16:57:00 +0000
committercce <devnull@localhost>2005-12-22 16:57:00 +0000
commitfbda14193ed13abe56be0cdf29bc7ca1405e4219 (patch)
tree052857f09eb14c9f78ef8d9616d9e3ed2497332c /paste/fileapp.py
parent79854f14c13bcc7ebdf41f8cac8dc032e261b411 (diff)
downloadpaste-fbda14193ed13abe56be0cdf29bc7ca1405e4219.tar.gz
- removed unnecessary spaces in several files
- added DataApp to paste.fileapp
Diffstat (limited to 'paste/fileapp.py')
-rw-r--r--paste/fileapp.py90
1 files changed, 78 insertions, 12 deletions
diff --git a/paste/fileapp.py b/paste/fileapp.py
index f285e00..a861fa3 100644
--- a/paste/fileapp.py
+++ b/paste/fileapp.py
@@ -1,11 +1,59 @@
"""
Static file sending application
"""
-import os
+import os, time
import mimetypes
import httpexceptions
+from response import has_header, remove_header
+from rfc822 import formatdate
+
+CACHE_SIZE = 4096
+BLOCK_SIZE = 4096
+
+class DataApp(object):
+ """
+ Returns an application that will send the data provided.
+
+ Constructor Arguments:
+
+ ``content`` the content being sent to the client
+
+ ``headers`` set of static headers to send /w response
+ - may contain ``content-type`` override
+ - must not contain ``content-length``
+
+ ``mimetype`` if set, this is the mimetype of the content
+
+ ``expires`` if this is set, is the number of seconds
+ from the time of the request that the file
+ is marked to expire
-class FileApp(object):
+ """
+ def __init__(self, content, headers=None, expires=None, mimetype=None):
+ self.content = None
+ self.headers = headers or []
+ self.expires = expires
+ if not has_header(self.headers,'content-type'):
+ if not mimetype:
+ mimetype = 'application/octet-stream'
+ self.headers.append(('content-type', mimetype))
+ if content:
+ self.set_content(content)
+
+ def set_content(self, content):
+ self.content = [content]
+ remove_header(self.headers,'content-length')
+ self.headers.append(('content-length',str(len(content))))
+
+ def __call__(self, environ, start_response):
+ headers = self.headers
+ if self.expires:
+ headers = headers[:] # copy this array so we can add
+ headers.append(('Expires',formatdate(time.time()+self.expires)))
+ start_response('200 OK',headers)
+ return self.content
+
+class FileApp(DataApp):
"""
Returns an application that will send the file at the given
filename. Adds a mime type based on ``mimetypes.guess_type()``.
@@ -13,15 +61,35 @@ class FileApp(object):
# @@: Should test things like last-modified, if-modified-since,
# etc.
- def __init__(self, filename):
+ def __init__(self, filename, **kwargs):
self.filename = filename
+ self.st_mtime = 0
+ if 'mimetype' not in kwargs:
+ mimetype, encoding = mimetypes.guess_type(self.filename)
+ # @@: I don't know what to do with the encoding.
+ if not mimetype:
+ mimetype = 'application/octet-stream'
+ kwargs['mimetype'] = mimetype
+ DataApp.__init__(self, None, **kwargs)
+
+ def update(self):
+ stat = os.stat(self.filename)
+ if stat.st_mtime == self.st_mtime:
+ return
+ self.st_mtime = stat.st_mtime
+ if stat.st_size < CACHE_SIZE:
+ fh = open(self.filename,"rb")
+ self.set_content(fh.read())
+ fh.close()
+ return
+ self.content = None
+ remote_header(self.headers,'content-length')
+ self.headers.append(('content-length',stat.st_size))
def __call__(self, environ, start_response):
- type, encoding = mimetypes.guess_type(self.filename)
- # @@: I don't know what to do with the encoding.
- if not type:
- type = 'application/octet-stream'
- size = os.stat(self.filename).st_size
+ self.update()
+ if self.content:
+ return DataApp.__call__(self, environ, start_response)
try:
file = open(self.filename, 'rb')
except (IOError, OSError), e:
@@ -29,14 +97,12 @@ class FileApp(object):
'You are not permitted to view this file (%s)' % e)
return exc.wsgi_application(
environ, start_response)
- start_response('200 OK',
- [('content-type', type),
- ('content-length', str(size))])
+ DataApp.__call__(self, environ, start_response)
return _FileIter(file)
class _FileIter:
- def __init__(self, fp, blocksize=4096):
+ def __init__(self, fp, blocksize=BLOCK_SIZE):
self.file = fp
self.blocksize = blocksize