wsgi-harakiri

WSGI Middleware that implements a customizable 'harakiri' like uWSGI


Keywords
WSGI, Harakiri
License
ISC
Install
pip install wsgi-harakiri==1.0.0

Documentation

WSGI Harakiri

Abandoned

Don't use this, it's not the best way to achieve a request timeout. You're probably better off using and improving any such feature built into your wsgi server, since it will terminate things more reliably.

WSGI Middleware that implements a customizable 'harakiri' like uWSGI.

Installation

Use pip:

pip install wsgi-harakiri

Tested on Python 2.7, 3.4, and 3.5.

Usage

Wrap your WSGI application with the middleware, for example for a Django application in your wsgi.py:

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproject.settings")

application = get_wsgi_application()

from wsgi_harakiri import HarakiriMiddleware

# By default adds a request timeout of 30 seconds
application = HarakiriMiddleware(application)

Your app must not be running a multi-threaded server (multi-process is ok), and it must be running on a POSIX system. The alarm system call is used, so this cannot be combined with other things that use it, e.g. the 'harakiri' functionality in uWSGI.

API

HarakiriMiddleware(application, timeout=30, on_harakiri=None, error_app=None)

Wraps a WSGI application with the harakiri functionality.

application may be any WSGI application.

timeout may be any integer number of seconds, and defaults to 30.

on_harakiri will be called when a harakiri occurs, from inside the alarm function - it is thus suitable for logging the stack trace that lead to the timeout. Its return value is ignored.

error_app is a second WSGI application that will be called to produce an error response when a timeout occurs. The default response is a rather plain '500 Internal server error' with HTML '<h1>Page load timeout</h1>'.

Example usage with all arguments:

application = get_wsgi_application()

from wsgi_harakiri import HarakiriMiddleware


def harakiri_handler():
    logger.error("Harakiri occured", extra={'stack': True})


def harakiri_page(environ, start_response):
    start_response(
        '500 Internal server error',
        [('Content-Type', 'text/html')]
    )
    return [b'<h1>Sorry, this page timed out.</h1>']


application = HarakiriMiddleware(
    application,
    timeout=15,
    on_harakiri=harakiri_handler,
    error_app=harakiri_page,
)

Harakiri

This is the exception that gets raised when a timeout occurs. You should not catch it anywhere in your code, however you could use it to detect when it happens inside a particular code path. For example:

from wsgi_harakiri import Harakiri


def find_users(search_term):
    conn = make_db_connection()
    try:
        return conn.query(search_term)
    except Harakiri:
        logger.error("A search timed out", extra={'search_term': search_term})
        raise