Create task after response delivery

How might one create a task after a successful response delivery? Many things can go wrong between response creation and delivery and I’d like to create an asyncio.task only after the transmission has completed and socket has closed.

What you want to use are signals.

To answer specifically, you want the http.lifecycle.complete signal. Something like this:

from sanic.signals import Event

@app.signal(Event.HTTP_LIFECYCLE_COMPLETE)
async def shutdown(conn_info):
    ...

But be careful with that one. It runs when the CONNECTION is closed as you asked. But if you have any sort of proxy in front of your application then it could be possible for two unrelated requests to be pipelined together into a single request.

Another alternative is to use http.lifecycle.response

@app.signal(Event.HTTP_LIFECYCLE_RESPONSE)
async def response(request, response):
    ...

This one will run when a request is complete. Think of it as super-late middleware. The only problem is that it WILL block the response bytes from being sent as it runs inline. That means you will need to dispatch a new task from inside this signal handler if you do not want to block the response.


Just curious, what sort of logic are you trying to achieve on socket close?

Thanks for the reply. The first option sounds good. I want to take some action after a successful http file transfer. If for some reason the file transfer does not complete such as an interruption during the transfer, I do not want to mark it as “successful”.

Just be mindful that a proxy client could hold that connection open a long time unrelated to your problem request. I generally would advise http.lifecycle.response for request related cleanup.