==============
How WSGI Works
==============

New to Werkzeug or even `WSGI`_? This part of the documentation covers the
low level parts of Werkzeug that are in fact just plain WSGI.

.. _WSGI: http://www.python.org/dev/peps/pep-0333/

What is WSGI?
=============

Basically WSGI is an interface between web servers and web applications.
We'll explain the mechanics of WSGI below, but to sum it up WSGI lets you
develop rich web application without the need to know about your server
environment. A WSGI application runs on standalone servers, on any
webserver out there, via `mod_python`, `FastCGI`, `CGI`, basically everything
that runs Python.

But there's much more; WSGI is more than just HTTP! You and other developers
can extend WSGI by adding new features to it, filtering input or output,
adding rich debugging systems, automatically send e-mails to your mailer
as soon as an unhandled application error occurs. You can add session
features to it etc.

There are few things you cannot do with WSGI, and Werkzeug itself is just
a tiny wrapper around WSGI, thus you don't lose any functionally unlike some
other implementations that abstract more. If you don't require all the power
of WSGI you can choose a higher level implementation like Django.

Writing a WSGI Application
==========================

The first part is about how to use WSGI without Werkzeug. You can read
the PEP (:pep:333) that defines it, but we'll do a very brief summary:

- a WSGI application is just a callable object that is passed an
  `environ` - a dict that contains request data, and a `start_response`
  function that is called to start sending the response.

  In order to send data to the server all you have to do is to call
  `start_response` and return an iterable.

- `environ` is a plain old CGI environment (contains values like `PATH_INFO`)
  in form of a python dict with some extensions like `wsgi.input` that
  represent the input stream.

- middlewares (we'll cover them later) can add additional data to the
  `environ`.

So, here's a simple application:

.. sourcecode:: python

    def application(environ, start_response):
        start_response('200 OK', [('Content-Type', 'text/html')])
        return ['Hello World!']

Now you have an application, but how can you start it? From Python 2.5,
the stdlib contains a WSGI server called `wsgiref`, for Python 2.4 and lower
you have to install that on your own. There are also other standalone
implementations which you can find online at `wsgi.org`_.

So to start the application as standalone server all you have to do is adding
this start hook to the file:

.. sourcecode:: python

    if __name__ == '__main__':
        from wsgiref.simple_server import make_server
        srv = make_server('localhost', 5000, application)
        srv.serve_forever()

When you now start the application you will see ``Hello World!`` on
``http://localhost:5000/``.

The `__name__` hook is a good idea so that you can use the module for other modules
like flup (provides a bridge to Apache and other webservers via FastCGI and
similar protocols) without altering the code.

.. _wsgi.org: http://www.wsgi.org/


Adding Interactive Elements
===========================

Let's extend the example from above so that we say ``Hello John`` if the
user visits ``http://localhost:5000/?name=John``:

.. sourcecode:: python

    from cgi import parse_qs, escape

    def application(environ, start_response):
        start_response('200 OK', [('Content-Type', 'text/html')])
        query = parse_qs(environ.get('QUERY_STRING', ''))
        return ['Hello %s!' % escape(query.get('name', 'World'))]

Basically we just combined the python CGI module with our WSGI application.


That Sucks!
===========

Indeed it does. It's neither fun to work with nor does it look clean and
simple. And that's where utilities like Werkzeug come into play. Werkzeug
for example lets you easily create unicode aware applications (in fact it
forces you to use unicode internally) and avoid repetitive work.

In this example we want to connect `/` with an index function and `/about`
with an about function, both returning different content. To keep the
example simple we just want to use a dict that maps to that and take advantage
or some of the Werkzeug features:

.. sourcecode:: python

    from cgi import escape
    from werkzeug.wrappers import BaseRequest, BaseResponse

    class Request(BaseRequest):
        charset = 'utf-8'

    class Response(BaseResponse):
        charset = 'utf-8'

    def index(req):
        return Response(u'''<h1>Index Page</h1>
        <p>What\'s your name?</p>
        <form action="hello" method="post">
            <input type="text" name="name" value="My Name">
            <input type="submit" value="Greet Me!">
        </form>
        ''', mimetype='text/html')

    def hello(req):
        name = req.form.get('name') or 'Nobody'
        return Response(u'<h1>Hello %s!</h1>' % escape(name),
                        mimetype='text/html')

    def about(req):
        return Response(u'''<h1>About This Page</h1>
            <p>This page is just a small example page for Werkzeug</p>
        ''', mimetype='text/html')

    def not_found(req):
        return Response(u'<h1>Page Not Found</h1>', status=404,
                        mimetype='text/html')

    views = {
        '/':        index,
        '/hello':   hello,
        '/about':   about
    }

    def application(environ, start_response):
        req = Request(environ)
        if req.path not in views:
            resp = not_found(req)
        else:
            resp = views[req.path](req)
        return resp(environ, start_response)

Alright. That's quite a lot of code but let's go step by step through it.

The first thing we do is importing the stuff we use. In that example we need
the `escape` function from the `cgi` module that SGML escapes strings. This
is required to avoid XSS attacks to the application. The next import gives
us the `BaseRequest` and `BaseResponse` objects we then subclass in order to
tell them to use utf-8 encoding. The default encoding is ASCII, thus we
wouldn't be able to use any non-ASCII characters.

Then we define a bunch of callback functions that just return HTML responses.
One of them - `not_found` - is called when we don't have a matching URL,
the others are bound to urls in the `views` dict.

The WSGI application itself just creates a request object and looks up the
callbacks or proceeds with the `not_found` function if there is no matching
URL. The return value of the response is then called as WSGI application.

Because `Response` objects behave like WSGI applications this is possible.

Of course this example is still bad code, in real applications you would use
one of the template engines that are available for Python. But for the simple
example that should be enough.


Debugging It
============

You probably have had a typo in one of the examples above. In that case you
don't have to use the error output from the wsgiref server. There are some
excellent debugging systems for WSGI, one of them is shipped with werkzeug
and explained in the `debug system`_ docs.

.. _debug system: debug.txt
