| 1 | import os | 
|---|
| 2 | import sys | 
|---|
| 3 | import imp | 
|---|
| 4 | import pkg_resources | 
|---|
| 5 | import mimetypes | 
|---|
| 6 | from paste import request | 
|---|
| 7 | from paste import fileapp | 
|---|
| 8 | from paste.util import import_string | 
|---|
| 9 | from paste.deploy import converters | 
|---|
| 10 | from paste import httpexceptions | 
|---|
| 11 | from paste.httpheaders import ETAG | 
|---|
| 12 |  | 
|---|
| 13 | from paste.urlparser import StaticURLParser | 
|---|
| 14 |  | 
|---|
| 15 | class CacheableStaticURLParser( StaticURLParser ): | 
|---|
| 16 |     def __init__( self, directory, cache_seconds=None ): | 
|---|
| 17 |         StaticURLParser.__init__( self, directory ) | 
|---|
| 18 |         self.cache_seconds = cache_seconds | 
|---|
| 19 |     def __call__( self, environ, start_response ): | 
|---|
| 20 |         path_info = environ.get('PATH_INFO', '') | 
|---|
| 21 |         if not path_info: | 
|---|
| 22 |             return self.add_slash(environ, start_response) | 
|---|
| 23 |         if path_info == '/': | 
|---|
| 24 |             # @@: This should obviously be configurable | 
|---|
| 25 |             filename = 'index.html' | 
|---|
| 26 |         else: | 
|---|
| 27 |             filename = request.path_info_pop(environ) | 
|---|
| 28 |         full = os.path.join(self.directory, filename) | 
|---|
| 29 |         if not os.path.exists(full): | 
|---|
| 30 |             return self.not_found(environ, start_response) | 
|---|
| 31 |         if os.path.isdir(full): | 
|---|
| 32 |             # @@: Cache? | 
|---|
| 33 |             return self.__class__(full)(environ, start_response) | 
|---|
| 34 |         if environ.get('PATH_INFO') and environ.get('PATH_INFO') != '/': | 
|---|
| 35 |             return self.error_extra_path(environ, start_response) | 
|---|
| 36 |         if_none_match = environ.get('HTTP_IF_NONE_MATCH') | 
|---|
| 37 |         if if_none_match: | 
|---|
| 38 |             mytime = os.stat(full).st_mtime | 
|---|
| 39 |             if str(mytime) == if_none_match: | 
|---|
| 40 |                 headers = [] | 
|---|
| 41 |                 ETAG.update(headers, mytime) | 
|---|
| 42 |                 start_response('304 Not Modified',headers) | 
|---|
| 43 |                 return [''] # empty body | 
|---|
| 44 |         app = fileapp.FileApp(full) | 
|---|
| 45 |         if self.cache_seconds: | 
|---|
| 46 |             app.cache_control( max_age = int( self.cache_seconds ) ) | 
|---|
| 47 |         return app(environ, start_response) | 
|---|
| 48 |          | 
|---|
| 49 | def make_static( global_conf, document_root, cache_seconds=None ): | 
|---|
| 50 |     return CacheableStaticURLParser( document_root, cache_seconds ) | 
|---|