Waitress WSGI Server

repository·main·Indexed 23 days ago

https://github.com/pylons/waitress

A production-quality, pure-Python WSGI server designed for high compatibility across Unix and Windows platforms with no external dependencies. It utilizes a hybrid model of asynchronous I/O and synchronous worker threads to manage connections and requests. Key features include the `serve()` entry point for starting servers, support for trusted proxies and header management, and implementation of `wsgi.file_wrapper` for efficient file serving.

Tokens
8.8K
Snippets
20
Records
49
Agent score
82%

What's inside waitress

  1. Overview of Waitress WSGI server

    main

    Waitress is a production-quality, pure-Python WSGI server designed for high performance with minimal dependencies. It is suitable for serving web applications that follow the WSGI standard.

    Key Features:

    • Zero external dependencies: Only relies on the Python standard library.
    • Cross-platform: Runs on CPython on both Unix and Windows.
    • Python Compatibility: Requires Python 3.9+ (CPython) or PyPy 3 (version 3.9 compatible and above) on UNIX.
    • Protocol Support: Supports HTTP/1.0 and HTTP/1.1.
  2. Overview of Waitress

    main

    Waitress is a production-quality, pure-Python WSGI server designed for acceptable performance with no external dependencies outside the Python standard library.

    Key Characteristics:

    • Platform Support: Runs on CPython on both Unix and Windows. It also supports PyPy 3 on Unix.
    • Python Version: Requires Python 3.9+.
    • Protocol Support: Supports HTTP/1.0 and HTTP/1.1.
    • TLS/SSL: Does not support TLS natively. To use HTTPS, you must run Waitress behind a reverse proxy (e.g., Nginx or Apache).
  3. How Waitress handles connections and requests

    main

    Waitress uses a hybrid model of asynchronous I/O and synchronous worker threads to manage client connections and HTTP requests:

    1. Asynchronous I/O (Main Thread): Waitress uses the wasyncore module (a vendored version of the deprecated asyncore) to handle all network I/O. The main thread uses select.select to monitor connections and determine when data can be read from or written to a client.
    2. Channels: For every TCP connection established by a client, Waitress creates a "channel". A single channel manages all HTTP requests sent over that specific connection (e.g., multiple requests in an HTTP/1.1 keep-alive session). When the connection closes, the channel is destroyed.
    3. Task Dispatching: Once a channel receives a complete, valid HTTP request, it schedules a "task" with a thread dispatcher.
    4. Worker Threads (Synchronous): The thread dispatcher manages a fixed pool of worker threads (defaulting to 4). These threads execute the actual application logic (the WSGI task).

    Key Architectural Constraints:

    • No I/O in Workers: Worker threads never perform I/O. They only process the request and write back to the channel's output buffer. This prevents slow clients from hanging worker threads.
    • Thread Exhaustion: Waitress does not attempt to kill "hung" threads. If your WSGI application logic enters an infinite loop, that worker thread is consumed indefinitely. If all worker threads are consumed by hung tasks, the server will stop responding to new requests.
  4. Understand WSGI requirements for Waitress

    main
    Waitress is a WSGI server. To use Waitress, your web application must implement the Web Server Gateway Interface (WSGI) standard. This standard provides a consistent way to connect Python web applications to web servers.
  5. Understand WSGI middleware

    main
    In the context of Waitress and WSGI, middleware is a component that acts as both a server and an application. It sits between the server and the application to perform tasks such as caching, content-transport encoding, or other request/response processing functions.
  6. Enable web traffic access logging with TransLogger

    main

    Waitress does not log web traffic (requests/responses) by default. To log web traffic in the Apache Combined Log Format, use the TransLogger middleware from the Paste library.

    When using TransLogger manually in Python, it will automatically set up a console handler unless setup_console_handler=False is passed.

    from mypackage import wsgiapp
    from waitress import serve
    from paste.translogger import TransLogger
    
    # Wrap the app in TransLogger to enable access logging
    serve(TransLogger(wsgiapp, setup_console_handler=False))
  7. Specify WSGI applications in waitress-serve

    main

    You can specify the WSGI application in waitress-serve using the format MODULE:OBJECT (similar to PasteDeploy).

    • Standard application: myapp.mymodule:wsgifunc
    • Attribute resolution: Use dots to resolve attributes, e.g., myapp.mymodule:appobj.wsgifunc.
    • Factory methods: If your framework uses a factory method to return a WSGI application, use the --call flag to invoke the object before serving.
  8. Configure WSGI environment using proxy headers

    main

    To allow Waitress to dynamically set the wsgi.url_scheme and other environment variables (like HTTP_HOST, REMOTE_ADDR, etc.) based on the incoming request, you can use proxy headers.

    1. Configure your proxy to send headers such as X-Forwarded-Proto, X-Forwarded-For, X-Forwarded-Host, and X-Forwarded-Port.
    2. Configure Waitress by setting trusted_proxy_headers to include the names of the headers you are using.
    3. Crucial: You must also configure the Waitress server's trusted_proxy setting to contain the IP address of your proxy server so that Waitress knows to trust these headers.

    Waitress also supports the RFC7239 Forwarded header. To use it, set trusted_proxy_headers = "forwarded".

  9. Deploy Waitress behind SSL proxies

    main

    When deploying Waitress behind an SSL-terminating proxy, you can ensure the application correctly identifies the protocol (HTTP vs HTTPS) using two methods:

    1. Explicit Parameter: Use the explicit wsgi.url_scheme parameter during deployment.
    2. Proxy Headers: Waitress allows trusted proxies to override wsgi.url_scheme for specific requests by supplying the X_FORWARDED_PROTO header.