Friday, August 26, 2016

Python Web Applications: The basics of WSGI

The basics of WSGI

Beneath Django, Flask, Bottle, and every other Python web framework, lies the Web Server Gateway Interface, or WSGI for short. WSGI is to Python what Servlets are to Java --- a common specification for web servers that allows different web servers and application frameworks to interact based on a common API. However, as with most things, the Python version is considerably simpler.

WSGI is defined in PEP 3333, which I encourage you to read as a reference if you want more information after this quick intro.

This article will introduce you to the WSGI spec from an application developer's perspective, and show you how to work directly with WSGI to create applications (if you so desire).

Your First WSGI App

Here's the most basic Python web app possible:

def app(environ, start_fn):
    start_fn('200', [('Content-Type', 'text/plain')])
    return ["Hello World!\n"]

That's it! The whole file. Call it app.py and run it with any WSGI-compatible server and you'll get a Hello World response with a 200 status. You can use gunicorn for this; just install it via pip (pip install gunicorn) and run it with gunicorn app:app. This command tells gunicorn to get the WSGI callable from the app variable in the app module.

Right now, you should be pretty excited. Just 3 lines for a running application? That must be some sort of record (barring PHP, because mod_php is cheating). I bet you're just raring to know more.

So what are the essential parts of a WSGI application?

  • A WSGI application is a Python callable, such as a function, a class, or a class instance with a __call__ method
  • The application callable must accept two arguments: the environ, which is a Python dict containing the request data, and start_fn, itself a callable.
  • The application must call the start_fn with two arguments: the status code (as a string), and a list of headers expressed as 2-tuples.
  • The application returns an iterable containing the bytes in the response body in handy, streamable chunks --- in this case, a list of strings containing just "Hello, World!". (If app is a class, this can be accomplished in the __iter__ method.)

By way of example, these next two examples are equivalent to the first:

class app(object):

    def __init__(self, environ, start_fn):
        self.environ = environ
        self.start_fn = start_fn

    def __iter__(self):
        self.start_fn('200', [('Content-Type', 'text/plain')])
        yield "Hello World!\n"

class Application(object):
    def __call__(self, environ, start_fn):
        start_fn('200', [('Content-Type', 'text/plain')])
        yield "Hello World!\n"

app = Application()

You might already be thinking of ways that you can use this information, but probably the most relevant one is writing middlewares.

Continue reading %Python Web Applications: The basics of WSGI%


by Adam Bard via SitePoint

No comments:

Post a Comment