Search code examples
rustcancellationrust-axumrust-futures

Is an Axum handler cancelled if the requester disconnects?


Consider the scenario where a client makes a request and a handler starts processing it, but then the client disconnects before receiving the response. Does Axum destroy the task associated with that connection immediately or does it let it continue running?

Whether it does or not effects how this edge case should be handled:

  • If the task is cancelled, not all user written code is inherently cancel-safe and would need to be accounted for (either meticulously or just wrapping it in a spawn).
  • If the task is not cancelled, the user may want to know that the response will not be received and could stop processing early.

A follow up question: are extractors and middleware handled the same?


Solution

  • Yes, if the underlying connection is closed while the request is being processed, it will destroy the future handling it.

    From this issue, this disscussion, this reddit thread, and from my own observations the handler is cancelled. This is an acceptable default because if you need to ensure the processing stays alive, its as simple as tokio::spawn. This can be done in a case-by-case manner in your handlers or can even be done in middleware if you always want that behavior:

    .route_layer(axum::middleware::from_fn(
        // this spawns every route request to protect against cancellation
        |req: Request<Body>, next: Next| async move {
            tokio::task::spawn(next.run(req)).await.unwrap()
        },
    ))
    

    Keep in mind that task cancellation is not the only thing that can stop your code from running so a holistic solution probably doesn't need to spawn, but can be desired regardless.