Back to index

moin  1.9.0~rc2
Public Member Functions | Public Attributes | Private Member Functions
MoinMoin.support.werkzeug.utils.SharedDataMiddleware Class Reference

List of all members.

Public Member Functions

def __init__
def is_allowed
def get_file_loader
def get_package_loader
def get_directory_loader
def generate_etag
def __call__

Public Attributes

 app
 exports
 cache
 cache_timeout
 is_allowed

Private Member Functions

def _opener

Detailed Description

A WSGI middleware that provides static content for development
environments or simple server setups. Usage is quite simple::

    import os
    from werkzeug import SharedDataMiddleware

    app = SharedDataMiddleware(app, {
        '/shared': os.path.join(os.path.dirname(__file__), 'shared')
    })

The contents of the folder ``./shared`` will now be available on
``http://example.com/shared/``.  This is pretty useful during development
because a standalone media server is not required.  One can also mount
files on the root folder and still continue to use the application because
the shared data middleware forwards all unhandled requests to the
application, even if the requests are below one of the shared folders.

If `pkg_resources` is available you can also tell the middleware to serve
files from package data::

    app = SharedDataMiddleware(app, {
        '/shared': ('myapplication', 'shared_files')
    })

This will then serve the ``shared_files`` folder in the `myapplication`
Python package.

The optional `disallow` parameter can be a list of :func:`~fnmatch.fnmatch`
rules for files that are not accessible from the web.  If `cache` is set to
`False` no caching headers are sent.

Currently the middleware does not support non ASCII filenames.  If the
encoding on the file system happens to be the encoding of the URI it may
work but this could also be by accident.  We strongly suggest using ASCII
only file names for static files.

.. versionchanged:: 0.5
   The cache timeout is configurable now.

:param app: the application to wrap.  If you don't want to wrap an
            application you can pass it :exc:`NotFound`.
:param exports: a dict of exported files and folders.
:param diallow: a list of :func:`~fnmatch.fnmatch` rules.
:param cache: enable or disable caching headers.
:Param cache_timeout: the cache timeout in seconds for the headers.

Definition at line 101 of file utils.py.


Constructor & Destructor Documentation

def MoinMoin.support.werkzeug.utils.SharedDataMiddleware.__init__ (   self,
  app,
  exports,
  disallow = None,
  cache = True,
  cache_timeout = 60 * 60 * 12 
)

Definition at line 150 of file utils.py.

00150 
00151                  cache_timeout=60 * 60 * 12):
00152         self.app = app
00153         self.exports = {}
00154         self.cache = cache
00155         self.cache_timeout = cache_timeout
00156         for key, value in exports.iteritems():
00157             if isinstance(value, tuple):
00158                 loader = self.get_package_loader(*value)
00159             elif isinstance(value, basestring):
00160                 if os.path.isfile(value):
00161                     loader = self.get_file_loader(value)
00162                 else:
00163                     loader = self.get_directory_loader(value)
00164             else:
00165                 raise TypeError('unknown def %r' % value)
00166             self.exports[key] = loader
00167         if disallow is not None:
00168             from fnmatch import fnmatch
00169             self.is_allowed = lambda x: not fnmatch(x, disallow)


Member Function Documentation

def MoinMoin.support.werkzeug.utils.SharedDataMiddleware.__call__ (   self,
  environ,
  start_response 
)

Definition at line 227 of file utils.py.

00227 
00228     def __call__(self, environ, start_response):
00229         # sanitize the path for non unix systems
00230         cleaned_path = environ.get('PATH_INFO', '').strip('/')
00231         for sep in os.sep, os.altsep:
00232             if sep and sep != '/':
00233                 cleaned_path = cleaned_path.replace(sep, '/')
00234         path = '/'.join([''] + [x for x in cleaned_path.split('/')
00235                                 if x and x != '..'])
00236         file_loader = None
00237         for search_path, loader in self.exports.iteritems():
00238             if search_path == path:
00239                 real_filename, file_loader = loader(None)
00240                 if file_loader is not None:
00241                     break
00242             if not search_path.endswith('/'):
00243                 search_path += '/'
00244             if path.startswith(search_path):
00245                 real_filename, file_loader = loader(path[len(search_path):])
00246                 if file_loader is not None:
00247                     break
00248         if file_loader is None or not self.is_allowed(real_filename):
00249             return self.app(environ, start_response)
00250 
00251         guessed_type = mimetypes.guess_type(real_filename)
00252         mime_type = guessed_type[0] or 'text/plain'
00253         f, mtime, file_size = file_loader()
00254 
00255         headers = [('Date', http_date())]
00256         if self.cache:
00257             timeout = self.cache_timeout
00258             etag = self.generate_etag(mtime, file_size, real_filename)
00259             headers += [
00260                 ('Etag', '"%s"' % etag),
00261                 ('Cache-Control', 'max-age=%d, public' % timeout)
00262             ]
00263             if not is_resource_modified(environ, etag, last_modified=mtime):
00264                 f.close()
00265                 start_response('304 Not Modified', headers)
00266                 return []
00267             headers.append(('Expires', http_date(time() + timeout)))
00268         else:
00269             headers.append(('Cache-Control', 'public'))
00270 
00271         headers.extend((
00272             ('Content-Type', mime_type),
00273             ('Content-Length', str(file_size)),
00274             ('Last-Modified', http_date(mtime))
00275         ))
00276         start_response('200 OK', headers)
00277         return wrap_file(environ, f)
00278 

Here is the call graph for this function:

def MoinMoin.support.werkzeug.utils.SharedDataMiddleware._opener (   self,
  filename 
) [private]

Definition at line 177 of file utils.py.

00177 
00178     def _opener(self, filename):
00179         return lambda: (
00180             open(filename, 'rb'),
00181             datetime.utcfromtimestamp(os.path.getmtime(filename)),
00182             int(os.path.getsize(filename))
00183         )

Here is the caller graph for this function:

def MoinMoin.support.werkzeug.utils.SharedDataMiddleware.generate_etag (   self,
  mtime,
  file_size,
  real_filename 
)

Definition at line 220 of file utils.py.

00220 
00221     def generate_etag(self, mtime, file_size, real_filename):
00222         return 'wzsdm-%d-%s-%s' % (
00223             mktime(mtime.timetuple()),
00224             file_size,
00225             adler32(real_filename) & 0xffffffff
00226         )

Here is the caller graph for this function:

Definition at line 209 of file utils.py.

00209 
00210     def get_directory_loader(self, directory):
00211         def loader(path):
00212             if path is not None:
00213                 path = os.path.join(directory, path)
00214             else:
00215                 path = directory
00216             if os.path.isfile(path):
00217                 return os.path.basename(path), self._opener(path)
00218             return None, None
00219         return loader

Here is the call graph for this function:

Definition at line 184 of file utils.py.

00184 
00185     def get_file_loader(self, filename):
00186         return lambda x: (os.path.basename(filename), self._opener(filename))

Here is the call graph for this function:

def MoinMoin.support.werkzeug.utils.SharedDataMiddleware.get_package_loader (   self,
  package,
  package_path 
)

Definition at line 187 of file utils.py.

00187 
00188     def get_package_loader(self, package, package_path):
00189         from pkg_resources import DefaultProvider, ResourceManager, \
00190              get_provider
00191         loadtime = datetime.utcnow()
00192         provider = get_provider(package)
00193         manager = ResourceManager()
00194         filesystem_bound = isinstance(provider, DefaultProvider)
00195         def loader(path):
00196             path = posixpath.join(package_path, path)
00197             if path is None or not provider.has_resource(path):
00198                 return None, None
00199             basename = posixpath.basename(path)
00200             if filesystem_bound:
00201                 return basename, self._opener(
00202                     provider.get_resource_filename(manager, path))
00203             return basename, lambda: (
00204                 provider.get_resource_stream(manager, path),
00205                 loadtime,
00206                 0
00207             )
00208         return loader

Here is the call graph for this function:

Subclasses can override this method to disallow the access to
certain files.  However by providing `disallow` in the constructor
this method is overwritten.

Definition at line 170 of file utils.py.

00170 
00171     def is_allowed(self, filename):
00172         """Subclasses can override this method to disallow the access to
00173         certain files.  However by providing `disallow` in the constructor
00174         this method is overwritten.
00175         """
00176         return True


Member Data Documentation

Definition at line 151 of file utils.py.

Definition at line 153 of file utils.py.

Definition at line 154 of file utils.py.

Definition at line 152 of file utils.py.

Definition at line 168 of file utils.py.


The documentation for this class was generated from the following file: