Skip to content

Signals #401

@alexdutton

Description

@alexdutton

To support altering headers before responses are sent, among other things, there should be a signals framework so people can hook into the response process. This would be extensible for other uses too. This issue follows on from #393.

The proposal is:

Create a new signals module, containing a Signal class. Its constructor takes a single argument, arguments, saying which arguments must be passed when dispatching the signal. This class has a method for checking that potential callbacks have a compatible signature. The module also contains instances of this class for individual types of signal (e.g. response_start = Signal({'request', 'response'}) — I can't yet think of what other signals might be useful).

Application gets a new _signals = defaultdict(list) and a @property that exposes a view of it. It gets a add_signal_callback(signal : Signal, callback : Callable) method, which checks that the callback is compatible (see above) and coerces the calback to a coroutine, before appending the callback to self._signals[signal].

Signal dispatching is done by Appllication.dispatch_signal(signal : Signal, kwargs : dict), which iterates through the registered signals, calling each in turn.

Response.start() is modified to dispatch the response_start signal after this line.

I don't think there's any need to create signals for the request creation phase, as the request can be modified safely with middleware.

The use-case of adding response headers from middleware becomes this slightly contrived example:

import asyncio
import time

from aiohttp.signals import response_start

@asyncio.coroutine
def add_header_middleware(app, handler):
    @asyncio.coroutine
    def middleware(request):
        request.started = time.time()
        return (yield from handler(request))
    return middleware

def add_request_started(*, request, response):
    response.headers['X-Started'] = str(request.started)

app = Application(middlewares=(add_header_middleware,))
app.add_signal_handler(response_start, add_request_started)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions