diff options
author | cce <devnull@localhost> | 2005-12-23 21:36:37 +0000 |
---|---|---|
committer | cce <devnull@localhost> | 2005-12-23 21:36:37 +0000 |
commit | 370ba732f785cc211e850664ecfea6a62fea30b4 (patch) | |
tree | bbc6b3281820448e64ada2ae5c45e39a0170e15a /paste/fileapp.py | |
parent | db53428a989dca0526d5f6a4bad5c91424424ea1 (diff) | |
download | paste-370ba732f785cc211e850664ecfea6a62fea30b4.tar.gz |
- got rid of unnecessary trailing spaces in httpexceptions
- made error messages us \r\n rather than just \n in httpexceptions
to comply with various browsers
- added tests to check FileApp
- added support for handling 100 Continue in httpserver
- fixingup dumpenviron in wsgilib to dump message body
- misc changes to fileapp (mostly documentation)
Diffstat (limited to 'paste/fileapp.py')
-rw-r--r-- | paste/fileapp.py | 50 |
1 files changed, 33 insertions, 17 deletions
diff --git a/paste/fileapp.py b/paste/fileapp.py index 4d2d860..118ba50 100644 --- a/paste/fileapp.py +++ b/paste/fileapp.py @@ -6,7 +6,9 @@ This module handles sending static content such as in-memory data or files. At this time it has cache helpers and understands the if-modified-since request header. """ + #@@: this still needs Range support for large files + import os, time import mimetypes import httpexceptions @@ -84,6 +86,7 @@ class DataApp(object): implementation does not support the enumeration of private fields + ``no_cache`` if True, this argument specifies that the response, as a whole, may be cashed; this implementation does not support the @@ -113,12 +116,18 @@ class DataApp(object): ``extensions`` gives additional cache-control extensionsn, such as items like, community="UCI" (14.9.6) - As recommended by RFC 2616, if ``max_age`` is provided (or - implicitly set by specifying ``no-cache``, then the ``Expires`` - header is also calculated for HTTP/1.0 clients. This is done + As recommended by RFC 2616, if ``max_age`` is provided, then + then the ``Expires`` header is also calculated for HTTP/1.0 + clients and proxies. For ``no-cache`` and for ``private`` + cases, we either do not want the response cached or do not want + any response accidently returned to other users; so to prevent + this case, we set the ``Expires`` header to the time of the + request, signifying to HTTP/1.0 transports that the content + isn't to be cached. If you are using SSL, your communication + is already "private", so to work with HTTP/1.0 browsers, + consider specifying your cache as public as the distinction + between public and private is moot for this case. """ - assert not has_header(self.headers,'cache-control') - assert not has_header(self.headers,'expires') assert isinstance(max_age,(type(None),int)) assert isinstance(s_maxage,(type(None),int)) result = [] @@ -146,7 +155,8 @@ class DataApp(object): for (k,v) in extensions.items(): assert '"' not in v result.append('%s="%s"' % (k.replace("_","-"),v)) - self.headers.append(('cache-control',", ".join(result))) + replace_header(self.headers,'cache-control',", ".join(result)) + return self def set_content(self, content): self.last_modified = time.time() @@ -154,6 +164,7 @@ class DataApp(object): replace_header(self.headers,'content-length', str(len(content))) replace_header(self.headers,'last-modified', formatdate(self.last_modified)) + return self def __call__(self, environ, start_response): if self.expires is not None: @@ -165,17 +176,17 @@ class DataApp(object): try: client_clock = mktime_tz(parsedate_tz(checkmod)) except TypeError: - return HTTPBadRequest( - "Bad Timestamp\n" - "Client program did not provide an appropriate " - "timestamp for its If-Modified-Since header." + return HTTPBadRequest(detail=( + "Client program provided an ill-formed timestamp for\r\n" + "its If-Modified-Since header:\r\n" + " %s\r\n") % checkmod ).wsgi_application(environ, start_response) if client_clock > time.time(): - return HTTPBadRequest(( - "Clock Time In Future\n" - "According to this server, the time provided in " - "the If-Modified-Since header (%s) is in the future.\n" - "Please check your system clock.") % checkmod + return HTTPBadRequest(detail=( + "Please check your system clock.\r\n" + "According to this server, the time provided in the\r\n" + "If-Modified-Since header is in the future:\r\n" + " %s\r\n") % checkmod ).wsgi_application(environ, start_response) elif client_clock <= self.last_modified: # the client has a recent copy @@ -190,10 +201,13 @@ class FileApp(DataApp): Returns an application that will send the file at the given filename. Adds a mime type based on ``mimetypes.guess_type()``. See DataApp for the arguments beyond ``filename``. + + """ def __init__(self, filename, headers=None, **kwargs): self.filename = filename + self.last_size = None content_type, content_encoding = mimetypes.guess_type(self.filename) if content_type and 'content_type' not in kwargs: kwargs['content_type'] = content_type @@ -203,9 +217,11 @@ class FileApp(DataApp): def update(self): stat = os.stat(self.filename) - if stat.st_mtime == self.last_modified: + if (stat.st_mtime == self.last_modified and + stat.st_size == self.last_size): return - if stat.st_size < CACHE_SIZE: + self.last_size = stat.st_size + if stat.st_size < CACHE_SIZE: fh = open(self.filename,"rb") self.set_content(fh.read()) fh.close() |