Foundations of Python Network Programming

(WallPaper) #1
Chapter 10 ■ http ServerS

171

After the debut of WSGI, the idea of WSGI middleware enjoyed a heyday—the idea that Python HTTP
services might in the future be designed from a series of concentric WSGI wrappers. One wrapper might provide
authentication. Another might catch exceptions and log them before returning a 500 Internal Server Error page. Yet
another might reverse-proxy legacy URLs to an old CMS still running in an organization and use Diazo (a project that
survives to this day) to re-theme it to match the organization’s more modern pages.
Although there are still developers who write and use WSGI middleware, most Python programmers today use
WSGI only for the pluggability that it offers between an application or framework and the web server that listens for
incoming HTTP requests.


Asynchronous Server-Frameworks


There is one application pattern, however, that has not been touched by the WSGI revolution, and that is
asynchronous servers, which support coroutines or green threads.
The design of the WSGI callable targets a traditional multithreaded or multiprocess server, and so the callable
is expected to block during any I/O that it needs to perform. WSGI offers no mechanism by which the callable
could hand control back to the main server thread so that other callables can take turns making progress. (See the
discussion of asynchrony in Chapter 7 to review how an asynchronous service splits its logic into small, nonblocking
snippets of code.)
Each asynchronous server framework has therefore had to offer its own conventions for writing a web
service. While these patterns vary in both brevity and convenience, they usually take responsibility for parsing the
incoming HTTP requests, and they sometimes offer conveniences for doing URL dispatch and committing database
connections automatically (see Chapter 11).
That is why the title of this section includes “Server-Frameworks.” Projects exploring async in Python must both
produce an HTTP web server atop their particular engine and then invent a calling convention whereby the request
information that they have parsed can be handed off to your own code. Unlike in the WSGI ecosystem, you cannot
pick an async HTTP server and web framework separately. Both are likely to come in the same package.
The Twisted server, which supports many different protocol handlers, has offered its own conventions for writing
a web service for more than a decade. More recently, Facebook developed and open sourced its Tornado engine that,
rather than support many protocols, focuses specifically on performance with HTTP alone. It supports a different set
of callback conventions than does Twisted. And the Eventlet project, whose green threads are implicitly asynchronous
instead of explicitly handing control back during each I/O operation, lets you write callables that look like normal
WSGI but that will silently yield control when they attempt blocking operations.
Looking toward the future, the inventor of Python—Guido van Rossum—has championed the new asyncio
engine in Python 3.4 (see Chapter 7) as providing a uniform interface by which different event-loop implementations
can plug into different asynchronous protocol frameworks. While this might help unite the variegated world of low-
level event loops, it does not appear that it will have any immediate effect on authors wanting to write asynchronous
HTTP services because it does not specify an API that specifically speaks the language of HTTP requests and
responses.
The limitation to keep in mind, if you are planning on writing an HTTP service using a specific async engine like
asyncio or Tornado or Twisted, is that you choose both your HTTP server and the framework that will help you parse
requests and compose responses. You will not be able to mix and match servers and frameworks.


Forward and Reverse Proxies


An HTTP proxy—whether forward or reverse—is an HTTP server that receives incoming requests and, at least for
some paths, turns around and becomes a client making an outgoing HTTP request to a server behind it, finally
passing that server’s response back to the original client. Read RFC 7230 Section 2.3 for an introduction to proxies and
how the design of HTTP anticipates their needs: https://tools.ietf.org/html/rfc7230#section-2.3.

Free download pdf