Source code for pulsar.apps.wsgi.handlers

from pulsar import Http404, isawaitable
from pulsar.utils.log import LocalMixin, local_method

from .utils import handle_wsgi_error
from .wrappers import WsgiResponse


[docs]class WsgiHandler: '''An handler for applications conforming to python WSGI_. .. attribute:: middleware List of :ref:`asynchronous WSGI middleware <wsgi-middleware>` callables which accept ``environ`` and ``start_response`` as arguments. The order matter, since the response returned by the callable is the non ``None`` value returned by a middleware. .. attribute:: response_middleware List of functions of the form:: def ..(environ, response): ... where ``response`` is a :ref:`WsgiResponse <wsgi-response>`. Pulsar contains some :ref:`response middlewares <wsgi-response-middleware>`. ''' def __init__(self, middleware=None, response_middleware=None, async=True): if middleware: middleware = list(middleware) self.middleware = middleware or [] self.response_middleware = response_middleware or [] self._async = async def __call__(self, environ, start_response): c = self._async_call if self._async else self._sync_call return c(environ, start_response) async def _async_call(self, environ, start_response): response = None try: for middleware in self.middleware: response = middleware(environ, start_response) if isawaitable(response): response = await response if response is not None: break if response is None: raise Http404 except Exception as exc: response = handle_wsgi_error(environ, exc) if isinstance(response, WsgiResponse) and not response.started: for middleware in self.response_middleware: response = middleware(environ, response) or response if isawaitable(response): response = await response response.start(start_response) return response def _sync_call(self, environ, start_response): response = None try: for middleware in self.middleware: response = middleware(environ, start_response) if response is not None: break if response is None: raise Http404 except Exception as exc: response = handle_wsgi_error(environ, exc) if isinstance(response, WsgiResponse) and not response.started: for middleware in self.response_middleware: response = middleware(environ, response) or response response.start(start_response) return response
[docs]class LazyWsgi(LocalMixin): '''A :ref:`wsgi handler <wsgi-handlers>` which loads the actual handler the first time it is called. Subclasses must implement the :meth:`setup` method. Useful when working in multiprocessing mode when the application handler must be a ``picklable`` instance. This handler can rebuild its wsgi :attr:`handler` every time is pickled and un-pickled without causing serialisation issues. ''' def __call__(self, environ, start_response): return self.handler(environ)(environ, start_response) @local_method def handler(self, environ=None): '''The :ref:`wsgi application handler <wsgi-handlers>` which is loaded via the :meth:`setup` method, once only, when first accessed. ''' return self.setup(environ)
[docs] def setup(self, environ=None): '''The setup function for this :class:`LazyWsgi`. Called once only the first time this application handler is invoked. This **must** be implemented by subclasses and **must** return a :ref:`wsgi application handler <wsgi-handlers>`. ''' raise NotImplementedError