diff options
Diffstat (limited to 'README.rst')
-rw-r--r-- | README.rst | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..332443f --- /dev/null +++ b/README.rst @@ -0,0 +1,189 @@ +Introduction +------------ + +Waitress is meant to be a production-quality pure-Python WSGI server with +very acceptable performance. It has no dependencies except ones which live +in the Python standard library. It runs on CPython on Unix and Windows under +Python 2.6+ and Python 3.2. It is also known to run on PyPy 1.6.0 on UNIX. +It supports HTTP/1.0 and HTTP/1.1. + +Usage +----- + +Here's normal usage of the server:: + + from waitress import serve + serve(wsgiapp, host='0.0.0.0', port=8080) + +If you want to serve your application on all IP addresses, on port 8080, you +can omit the ``host`` and ``port`` arguments and just call ``serve`` with the +WSGI app as a single argument:: + + from waitress import serve + serve(wsgiapp) + +Press Ctrl-C to exit the server. + +There's an entry point for PasteDeploy_ (``egg:waitress#main``) that lets you +use waitress's WSGI gateway from a configuration file, e.g.:: + + [server:main] + use = egg:waitress#main + host = 127.0.0.1 + port = 8080 + +Using Behind a Reverse Proxy +---------------------------- + +If you're using Waitress behind a reverse proxy, you'll almost always want +your reverse proxy to pass along the ``Host`` header sent by the client to +Waitress, in either case, as it will be used by most applications to generate +correct URLs. + +For example, when using Nginx as a reverse proxy, you might add the following +lines in a ``location`` section:: + + proxy_set_header Host $host; + +The Apache directive named ``ProxyPreserveHost`` does something similar when +used as a reverse proxy. + +Unfortunately, even if you pass the ``Host`` header, the Host header does not +contain enough information to regenerate the original URL sent by the client. +For example, if your reverse proxy accepts HTTPS requests (and therefore URLs +which start with ``https://``), the URLs generated by your application when +used behind a reverse proxy served by waitress might inappropriately be +``http://foo`` rather than ``https://foo``. To fix this, you'll want to +change the ``wsgi.url_scheme`` in the WSGI environment before it reaches your +application. You can do this in one of two ways: + +1. You can pass a ``url_scheme`` configuration variable to the + ``waitress.serve`` function. + +2. You can use Paste's ``PrefixMiddleware`` in conjunction with + configuration settings on the reverse proxy server. + +Using ``url_scheme`` to set ``wsgi.url_scheme`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can have the waitress server use the ``https`` url scheme by default. + + from waitress import serve + serve(wsgiapp, host='0.0.0.0', port=8080, url_scheme='https') + +This works if all URLs generated by your application should use the ``https`` +scheme. + +Using Paste's ``PrefixMiddleware`` to set ``wsgi.url_scheme`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If only some of the URLs generated by your application should use the +``https`` scheme (and some should use ``http``), you'll need to use Paste's +``PrefixMiddleware`` as well as change some configuration settings on your +proxy. To use ``PrefixMiddleware``, wrap your application before serving it +using waitress:: + + from waitress import serve + from paste.deploy.config import PrefixMiddleware + app = PrefixMiddleware(app) + serve(app) + +Once you wrap your application in the the ``PrefixMiddleware``, the +middleware will notice certain headers sent from your proxy and will change +the ``wsgi.url_scheme`` and possibly other WSGI environment variables +appropriately. + +Once your application is wrapped by the prefix middleware, you should +instruct your proxy server to send along the original ``Host`` header from +the client to your waitress server, as well as sending along a +``X-Forwarded-Proto`` header with the appropriate value for +``wsgi.url_scheme``. + +If your proxy accepts both HTTP and HTTPS URLs, and you want your application +to generate the appropriate url based on the incoming scheme, also set up +your proxy to send a ``X-Forwarded-Proto`` with the original URL scheme along +with each proxied request. For example, when using Nginx:: + + proxy_set_header X-Forwarded-Proto $scheme; + +It's permitted to set an ``X-Forwarded-For`` header too; the +``PrefixMiddleware`` uses this to adjust other environment variables (you'll +have to read its docs to find out which ones, I don't know what they are). For +the ``X-Forwarded-For`` header:: + + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + +Note that you can wrap your application in the PrefixMiddleware declaratively +in a PasteDeploy_ configuration file too, if your web framework uses +PasteDeploy-style configuration:: + + [app:myapp] + use = egg:mypackage#myapp + + [filter:paste_prefix] + use = egg:PasteDeploy#prefix + + [pipeline:main] + pipeline = + paste_prefix + myapp + + [server:main] + use = egg:waitress#main + host = 127.0.0.1 + port = 8080 + +Why? +---- + +At the time of the release of Waitress, there are already many pure-Python +WSGI servers. Why would we need another? + +Waitress is meant to be useful to web framework authors who require broad +platform support. It's neither the fastest nor the fanciest WSGI server +available but using it helps eliminate the N-by-M documentation burden +(e.g. production vs. deployment, Windows vs. Unix, Python 3 vs. Python 2, +PyPy vs. CPython) and resulting user confusion imposed by spotty platform +support of the current (2012-ish) crop of WSGI servers. For example, +``gunicorn`` is great, but doesn't run on Windows. ``paste.httpserver`` is +perfectly serviceable, but doesn't run under Python 3 and has no dedicated +tests suite that would allow someone who did a Python 3 port to know it +worked after a port was completed. ``wsgiref`` works fine under most any +Python, but it's a little slow and it's not recommended for production use as +it has not been audited for security issues. + +At the time of this writing, some existing WSGI servers already claim wide +platform support and have serviceable test suites. The CherryPy WSGI server, +for example, targets Python 2 and Python 3 and it can run on UNIX or Windows. +However, it is not distributed separately from its eponymous web framework, +and requiring a non-CherryPy web framework to depend on the CherryPy web +framework distribution simply for its server component is awkward. The test +suite of the CherryPy server also depends on the CherryPy web framework, so +even if we forked its server component into a separate distribution, we would +have still needed to backfill for all of its tests. + +Finally, I wanted the control that is provided by maintaining my own server. +A WSGI server is an important dependency of my web framework, and being able +to make arbitrary changes (add features, fix bugs, etc) without anyone else's +permission is nice. + +Waitress is a fork of the WSGI-related components which existed in +``zope.server``. ``zope.server`` had passable framework-independent test +coverage out of the box, and a good bit more coverage was added during the +fork. ``zope.server`` has existed in one form or another since about 2001, +and has seen production usage since then, so Waitress is not exactly +"another" server, it's more a repackaging of an old one that was already +known to work fairly well. + +Known Issues +------------ + +- Does not support the ``wsgi.file_wrapper`` protocol. + +- Does not do transfer-encoding: chunked responses (although handles chunked + requests fine). + +- Does not yet support IPv6. + +.. _PasteDeploy: http://pythonpaste.org/deploy/ + |