Middleware

from_fn #

  • Be an async fn.
  • Take one or more extractors as the first arguments.
  • Take Next<B> as the final argument.
  • Return something that implements IntoResponse.
async fn my_middleware<B>(
	request: Request<B>, // extractors*
	next: Next<B>,       // 最后一个参数必须是 next
) -> Response {          // 返回 IntoResponse
    // request 相关
    // ...
    
    // 调用下游 next 
    let response = next.run(request).await; 
    
    // response 相关
    // ...
    
    // 返回response
    response
}

let app = Router::new()
    .route("/", get(|| async { "Hello, world!" }))
    .layer(middleware::from_fn(my_middleware));
async fn auth<B>(    
    TypedHeader(auth): TypedHeader<Authorization<Bearer>>,    
    request: Request<B>,
    next: Next<B>, // the last: `next`
) -> Result<Response, StatusCode> {
    if token_is_valid(auth.token()) {
        let response = next.run(request).await;
        Ok(response)
    } else {
        Err(StatusCode::UNAUTHORIZED)
    }
}

fn token_is_valid(token: &str) -> bool {
    // ...
}

let app = Router::new()
    .route("/", get(|| async { /* ... */ }))
    .route_layer(middleware::from_fn(auth));

from_fn_with_state #

#[derive(Clone)]
struct AppState { /* ... */ }

async fn my_middleware<B>(
    State(state): State<AppState>,
    // you can add more extractors here but the last
    // extractor must implement `FromRequest` which
    // `Request` does
    request: Request<B>,
    next: Next<B>,
) -> Response {
    // do something with `request`...

    let response = next.run(request).await;

    // do something with `response`...

    response
}

let state = AppState { /* ... */ };

let app = Router::new()
    .route("/", get(|| async { /* ... */ }))
    .route_layer(middleware::from_fn_with_state(state.clone(), my_middleware))
    .with_state(state);