WSGI: Web Server Gateway Interface

Example 2: Using a generator for the response body

When serving up an HTML or similar page, it is probably the most
common case to render a template to a string and then return a one
item list which contains that string.

body = template.render(context=context, view=view)
return [body,]

What if you are delivering a large payload and don't want to store
the whole thing in memory at once? Use an iterable!

WSGI: Web Server Gateway Interface

Example 2: Using a generator for the response body

An easy way to make an iterator in Python is to use a
generator. Let's say we have an application that servies static
files. We could write a generator like this that serves
files one chunk at a time, so we only have to store
BLOCK_SIZE bytes of the file in memory at any given moment.

WSGI: Web Server Gateway Interface

WSGI Filters (aka Middleware)

Because the WSGI spec is so compact and just specifies a signature
for a callable, it is easy to conceive of and implement WSGI
applications which call other WSGI implementations, either modifying
the request on the way in, the response on the way out, or both.

Such applications are often called middleware applications or
filters. Filters can be chained together and the resulting chain
is generally referred to as a pipeline.

WSGI: Web Server Gateway Interface

Example 3: Serve static files from middleware

Instead of returning a 404 if we don't find a file, we delegate to
the wrapped application. So this:

# If file does not exist, return 404
if not os.path.exists(file_path):
return self._not_found(start_response)

Becomes this:

# If file does not exist, delegate to wrapped application
if not os.path.isfile(file_path):
return self.application(environ, start_response)

WSGI: Web Server Gateway Interface

Webob

WSGI was intentionally designed to be minimal for ease of
implementation for web servers and for ease of adoption by
application programmers.

No one likes to manipulate environ directly, nor does anyone
really like using start_response very much. The API
provided by WSGI, while easy to implement, is not particularly
satisfying to use semantically.

Nearly every application or framework I've seen based on WSGI has
invented some sort of request and response objects to
wrap manipulation of environ and start_response in
a more semantic, less error prone shell.

Webob has emerged as the canonical implementation for request
and response objects. Webob makes WSGI easier and more
satisfying to use.

WSGI: Web Server Gateway Interface

Example 4: Convert to Webob

We can convert our previous example to use Webob request and response
objects. First, in our FileServer filter we can encapsulate
the conversion from the WSGI api to Webob in one place and then
use just Webob throughout the rest of the application:

WSGI: Web Server Gateway Interface

PasteDeploy: Factories

WSGI contains only a specification for calling WSGI applications. It
does not contain a specification for constructing applications.

In order to be able to configure WSGI applications declaratively,
PasteDeploy needs a specification for constructing applications.
To this end, PasteDeploy has defined signatures for factory methods.
Implementing a factory interface means your application can be
constructed by PasteDeploy.

The signature for an application factory in PasteDeploy is as
follows:

def app_factory(global_config, **local_conf)

The signature for a filter application factory in PasteDeply is:

def filter_app_factory(app, global_conf, **local_conf)

In both of these signatures, global_conf is a dictionary
containing configuration parameters declared globally in the
PasteDeploy configuration for your site. local_conf
are keyword arguments containing configuration parameters that
match those configured for your component in PasteDeploy.

WSGI: Web Server Gateway Interface

Example 5: Deploy our sample app with PasteDeploy

A factory is any callable that creates and returns an object.
Specifically, in this case, we are concerned with factories that
create and return WSGI applications.

All classes are factories. They can be called and they return
objects.

In the case of our FileServer, class, then to make it work with
PasteDeploy we only need to change the signature of the
__init__ method from this:

def __init__(self, application, path):

To this:

def __init__(self, application, global_conf, path):

path is configured in the PasteDeploy configuration file
and is passed in by PasteDeploy here as a keyword argument.

Some care must be taken to make sure configuration parameters
declared in the PasteDeploy config match up with keyword arguments
in the factory callables.

WSGI: Web Server Gateway Interface

Example 5: Deploy our sample app with PasteDeploy

For the printenv application, we show another way to create
an application factory.

Here we use a closure to make our configuration parameters
available to our WSGI callable: