Add python-eventlet 0.16.1
[packages/trusty/python-eventlet.git] / eventlet / doc / modules / wsgi.rst
1 :mod:`wsgi` -- WSGI server
2 ===========================
3
4 The wsgi module provides a simple and easy way to start an event-driven
5 `WSGI <http://wsgi.org/wsgi/>`_ server.  This can serve as an embedded
6 web server in an application, or as the basis for a more full-featured web
7 server package.  One such package is `Spawning <http://pypi.python.org/pypi/Spawning/>`_.
8
9 To launch a wsgi server, simply create a socket and call :func:`eventlet.wsgi.server` with it::
10
11     from eventlet import wsgi
12     import eventlet
13
14     def hello_world(env, start_response):
15         start_response('200 OK', [('Content-Type', 'text/plain')])
16         return ['Hello, World!\r\n']
17
18     wsgi.server(eventlet.listen(('', 8090)), hello_world)
19
20
21 You can find a slightly more elaborate version of this code in the file
22 ``examples/wsgi.py``.
23
24 .. automodule:: eventlet.wsgi
25         :members:
26
27 .. _wsgi_ssl:
28
29 SSL
30 ---
31
32 Creating a secure server is only slightly more involved than the base example.  All that's needed is to pass an SSL-wrapped socket to the :func:`~eventlet.wsgi.server` method::
33
34     wsgi.server(eventlet.wrap_ssl(eventlet.listen(('', 8090)),
35                                   certfile='cert.crt',
36                                   keyfile='private.key',
37                                   server_side=True),
38                 hello_world)
39
40 Applications can detect whether they are inside a secure server by the value of the ``env['wsgi.url_scheme']`` environment variable.
41
42
43 Non-Standard Extension to Support Post Hooks
44 --------------------------------------------
45 Eventlet's WSGI server supports a non-standard extension to the WSGI
46 specification where :samp:`env['eventlet.posthooks']` contains an array of
47 `post hooks` that will be called after fully sending a response. Each post hook
48 is a tuple of :samp:`(func, args, kwargs)` and the `func` will be called with
49 the WSGI environment dictionary, followed by the `args` and then the `kwargs`
50 in the post hook.
51
52 For example::
53
54     from eventlet import wsgi
55     import eventlet
56
57     def hook(env, arg1, arg2, kwarg3=None, kwarg4=None):
58         print('Hook called: %s %s %s %s %s' % (env, arg1, arg2, kwarg3, kwarg4))
59
60     def hello_world(env, start_response):
61         env['eventlet.posthooks'].append(
62             (hook, ('arg1', 'arg2'), {'kwarg3': 3, 'kwarg4': 4}))
63         start_response('200 OK', [('Content-Type', 'text/plain')])
64         return ['Hello, World!\r\n']
65
66     wsgi.server(eventlet.listen(('', 8090)), hello_world)
67
68 The above code will print the WSGI environment and the other passed function
69 arguments for every request processed.
70
71 Post hooks are useful when code needs to be executed after a response has been
72 fully sent to the client (or when the client disconnects early). One example is
73 for more accurate logging of bandwidth used, as client disconnects use less
74 bandwidth than the actual Content-Length.
75
76
77 "100 Continue" Response Headers
78 -------------------------------
79
80 Eventlet's WSGI server supports sending (optional) headers with HTTP "100 Continue"
81 provisional responses.  This is useful in such cases where a WSGI server expects
82 to complete a PUT request as a single HTTP request/response pair, and also wants to
83 communicate back to client as part of the same HTTP transaction.  An example is
84 where the HTTP server wants to pass hints back to the client about characteristics
85 of data payload it can accept.  As an example, an HTTP server may pass a hint in a
86 header the accompanying "100 Continue" response to the client indicating it can or
87 cannot accept encrypted data payloads, and thus client can make the encrypted vs
88 unencrypted decision before starting to send the data).  
89
90 This works well for WSGI servers as the WSGI specification mandates HTTP
91 expect/continue mechanism (PEP333).
92
93 To define the "100 Continue" response headers, one may call
94 :func:`set_hundred_continue_response_header` on :samp:`env['wsgi.input']`
95 as shown in the following example::
96
97     from eventlet import wsgi
98     import eventlet
99
100     def wsgi_app(env, start_response):
101         # Define "100 Continue" response headers
102         env['wsgi.input'].set_hundred_continue_response_headers(
103             [('Hundred-Continue-Header-1', 'H1'),
104              ('Hundred-Continue-Header-k', 'Hk')])
105         # The following read() causes "100 Continue" response to
106         # the client.  Headers 'Hundred-Continue-Header-1' and 
107         # 'Hundred-Continue-Header-K' are sent with the response
108         # following the "HTTP/1.1 100 Continue\r\n" status line
109         text = env['wsgi.input'].read()
110         start_response('200 OK', [('Content-Length', str(len(text)))])
111         return [text]
112
113 You can find a more elaborate example in the file:
114 ``tests/wsgi_test.py``, :func:`test_024a_expect_100_continue_with_headers`.
115
116
117 Per HTTP RFC 7231 (http://tools.ietf.org/html/rfc7231#section-6.2) a client is
118 required to be able to process one or more 100 continue responses.  A sample
119 use case might be a user protocol where the server may want to use a 100-continue
120 response to indicate to a client that it is working on a request and the 
121 client should not timeout.
122
123 To support multiple 100-continue responses, evenlet wsgi module exports
124 the API :func:`send_hundred_continue_response`.
125
126 Sample use cases for chunked and non-chunked HTTP scenarios are included
127 in the wsgi test case ``tests/wsgi_test.py``,
128 :func:`test_024b_expect_100_continue_with_headers_multiple_chunked` and
129 :func:`test_024c_expect_100_continue_with_headers_multiple_nonchunked`.
130