A Functional Approach to Web Services
Pragmatic WSGI applications
The intent of the WSGI standard is not to define a complete web framework; the
intent is to define a minimum set of standards that allow flexible interoperability
of web-related processing. A framework can take a wildly different approach than
an internal architecture to provide web services. However, its outermost interface
should be compatible with WSGI so that it can be used in a variety of contexts.
Web servers such as Apache httpd and Nginx have adapters, which provide a
WSGI-compatible interface from the web server to Python applications. For more
information on WSGI implementations, visit
https://wiki.python.org/moin/WSGIImplementations.
Embedding our applications in a larger server allows us to have a tidy separation
of concerns. We can use Apache httpd to serve completely static content, such as
.css, .js, and image files. For HTML pages, though, we can use Apache's mod_wsgi
interface to hand off requests to a separate Python process, which handles only the
interesting HTML portions of the web content.
This means that we must either create a separate media server, or define our website
to have two sets of paths. If we take the second approach, some paths will have the
completely static content and can be handled by Apache httpd. Other paths will have
dynamic content, which will be handled by Python.
When working with WSGI functions, it's important to note that we can't modify
or extend the WSGI interface in any way. For example, it seems like a good idea to
provide an additional parameter with a sequence of functions that define the chain
of processing. Each stage would pop the first item from the list as the next step in the
processing. An additional parameter like this might be typical for functional design,
but the change in the interface defeats the purpose of WSGI.
A consequence of the WSGI definition is that configuration is either done with
global variables, the request environment, or with a function, which fetches some
global configuration objects from a cache. Using module-level globals works for
small examples. For more complex applications, a configuration cache might be
required. It might also be sensible to have a WSGI app, which merely updates the
environ dictionary with configuration parameters and passes control to another
WSGI application.