Filters

Filters are a collection of useful(in the authors opinion) wsgi middleware that is more client-centric than server-centric, you may find it useful too.

http_capture_filter

this filter captures the request and response and calls a function you provide so that you can do what you will. it’s important to note that the request and response you recieve are copies and modifying them does not effect the request or the response going to the application or client.

It is primarily used by the http_log_filter

def http_capture_filter(app, callback=lambda request, response: True):
    """
    captures request and response and passes off to a callback

    :rtype: :ref:`wsgi_application`

    :param app: inner :ref:`wsgi_application`

    :param callback: function to call
    """

    def m(environ, start_response):
        request = Request(environ)
        response = request.get_response(app)
        callback(request.copy(), response.copy())
        return response(environ, start_response)
    return m

http_log_filter

The http_log_filter will log both the request and the response to the log_level you provide. The default level is “DEBUG”, it’s handy when you need to see what the http traffic looks like in your application, but using it in production would insure you have huge log files that you would likely never read.

def http_log_filter(app, level="DEBUG"):
    """
    logs the request and response to the logger http_log at whatever
    level you specify

    :rtype: :ref:`wsgi_application`

    :param app: inner :ref:`wsgi_application`

    :param level: log level
    """
    level_int = logging._checkLevel(level)
    log = logging.getLogger("http_log")

    def _log_it(request, response):
        log.log(level=level_int, msg=l.PRINT_REQ(request))
        log.log(level=level_int, msg=l.PRINT_RES(response))
    return http_capture_filter(app, callback=_log_it)

charset_filter

Some websites won’t specify a charset on the response, this can sometimes be problematic. this filter will check if the charset attribute is set, and if it isn’t it will set it to utf8 which is a pretty safe bet in most cases.

def charset_filter(app):
    """
    if charset is missing, set it to a pretty much safe utf8

    :rtype: :ref:`wsgi_application`

    :param app: inner :ref:`wsgi_application`

    """
    def m(environ, start_response):
        request = Request(environ)
        res = request.get_response(app)
        if not res.charset:
            res.charset = "utf8"
        return res(environ, start_response)
    return m

decode_filter

Websites can return compressed responses. This filter will handle de-compressing them if a compressed response is detected.

def decode_filter(app):
    """
    decode the content(in case it's gzipped)

    BUG: for some reason, appengine doesn't respond to this and
    doesn't send gziped when asked.

    :rtype: :ref:`wsgi_application`

    :param app: inner :ref:`wsgi_application`

    """
    def m(environ, start_response):
        request = Request(environ)
        request.accept_encoding = "gzip"
        response = request.get_response(app)
        response.decode_content()
        return response(environ, start_response)
    return m

assert_filter

Sometimes you want to raise an error if you get a response under certain conditions. This filter allows you to specify a function to do that assertion before the response is returned. The function you specify will be passed a copy of the request and response.

def assert_filter(app, assert_=lambda request, response: True):
    """
    will allow for assertions to be made on the request and response.

    :rtype: :ref:`wsgi_application`

    :param app: inner :ref:`wsgi_application`

    """
    def m(environ, start_response):
        request = Request(environ)
        response = request.get_response(app)
        assert_(request.copy(), response.copy())
        return response(environ, start_response)

    return m

Usage

Filters can be combined to suit your needs. For example you could compose a wsgi application to support cookies and compressed responses and raise an error if the inner application responds with a status code of “401”, which means access denied.

"""
using filters
"""
from webobtoolkit import filters
from webob import Request, Response
import datetime


def time_application(environ, start_response):
    body = "the current time is %s " % datetime.datetime.now().isoformat()
    return Response(body)(environ, start_response)


# add cookie support
application = filters.cookie_filter(time_application)

# decompress the response if it is compressed
application = filters.decode_filter(time_application)


# raise an error the app returns something other than a 200 success
# response
def assert_success(request, response):
    assert response.status_int == 200, "the request was not sucessful"


application = filters.assert_filter(time_application, assert_=assert_success)

response = Request.blank("/").get_response(application)

print str(response)

Reference

filters for taking care of various aspects of HTTP

class webobtoolkit.filters.RequestCookieAdapter(request)

this class merely provides the methods required for a cookielib.CookieJar to work on a webob.Request

potential for yak shaving...very high

class webobtoolkit.filters.ResponseCookieAdapter(response)

this class merely provides methods required for a cookielib.CookieJar to work on a webob.Response

webobtoolkit.filters.assert_filter(app, assert_=<function <lambda>>)

will allow for assertions to be made on the request and response.

Return type:WSGI Application
Parameters:app – inner WSGI Application
webobtoolkit.filters.auto_redirect_filter(app, limit=10)

intercepts response, if response.status is redirectish(301, 302) will make the next call

webobtoolkit.filters.charset_filter(app)

if charset is missing, set it to a pretty much safe utf8

Return type:WSGI Application
Parameters:app – inner WSGI Application
webobtoolkit.filters.cookie_filter(app)

intercepts req/res and keeps track of cookies

Return type:WSGI Application
Parameters:app – inner WSGI Application
webobtoolkit.filters.decode_filter(app)

decode the content(in case it’s gzipped)

BUG: for some reason, appengine doesn’t respond to this and doesn’t send gziped when asked.

Return type:WSGI Application
Parameters:app – inner WSGI Application
webobtoolkit.filters.http_capture_filter(app, callback=<function <lambda>>)

captures request and response and passes off to a callback

Return type:

WSGI Application

Parameters:
webobtoolkit.filters.http_log_filter(app, level='DEBUG')

logs the request and response to the logger http_log at whatever level you specify

Return type:

WSGI Application

Parameters: