> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/tokio-rs/axum/llms.txt
> Use this file to discover all available pages before exploring further.

# Middleware

> Transform requests and responses with Axum middleware

Middleware allows you to process requests before they reach handlers and modify responses before they're sent to clients. Axum supports both custom middleware and Tower middleware.

## Middleware with `from_fn`

The simplest way to create middleware is using `middleware::from_fn`:

```rust theme={null}
use axum::{
    Router,
    routing::get,
    middleware::{self, Next},
    extract::Request,
    response::Response,
};

async fn my_middleware(
    request: Request,
    next: Next,
) -> Response {
    // Do something with the request...
    println!("Request: {} {}", request.method(), request.uri());
    
    // Call the next middleware or handler
    let response = next.run(request).await;
    
    // Do something with the response...
    println!("Response status: {}", response.status());
    
    response
}

let app = Router::new()
    .route("/", get(|| async { "Hello, World!" }))
    .layer(middleware::from_fn(my_middleware));
```

## Middleware signature

Middleware functions created with `from_fn` must:

<Steps>
  <Step title="Be an async function">
    The middleware must be an `async fn`.
  </Step>

  <Step title="Take extractors (optional)">
    Can take zero or more `FromRequestParts` extractors before the request.

    ```rust theme={null}
    use axum::{
        extract::Request,
        http::HeaderMap,
        middleware::Next,
        response::Response,
    };

    async fn middleware(
        headers: HeaderMap,  // Extractor
        request: Request,
        next: Next,
    ) -> Response {
        next.run(request).await
    }
    ```
  </Step>

  <Step title="Take Request">
    Must take exactly one `Request` as second-to-last argument.
  </Step>

  <Step title="Take Next">
    Must take `Next` as the last argument.
  </Step>

  <Step title="Return IntoResponse">
    Must return something that implements `IntoResponse`.
  </Step>
</Steps>

## Using extractors in middleware

Extract data from requests in middleware:

```rust theme={null}
use axum::{
    Router,
    routing::get,
    middleware::{self, Next},
    extract::Request,
    response::Response,
    http::{HeaderMap, StatusCode},
};

async fn auth_middleware(
    headers: HeaderMap,
    request: Request,
    next: Next,
) -> Result<Response, StatusCode> {
    // Check authorization header
    match headers.get("authorization") {
        Some(token) if is_valid_token(token) => {
            Ok(next.run(request).await)
        }
        _ => Err(StatusCode::UNAUTHORIZED),
    }
}

fn is_valid_token(_token: &axum::http::HeaderValue) -> bool {
    true // Simplified validation
}

let app = Router::new()
    .route("/protected", get(|| async { "Secret data" }))
    .layer(middleware::from_fn(auth_middleware));
```

## Middleware with state

Access application state in middleware using `from_fn_with_state`:

```rust theme={null}
use axum::{
    Router,
    routing::get,
    extract::{State, Request},
    middleware::{self, Next},
    response::Response,
    http::StatusCode,
};

#[derive(Clone)]
struct AppState {
    api_key: String,
}

async fn require_api_key(
    State(state): State<AppState>,
    request: Request,
    next: Next,
) -> Result<Response, StatusCode> {
    let provided_key = request
        .headers()
        .get("x-api-key")
        .and_then(|v| v.to_str().ok());
    
    if provided_key == Some(&state.api_key) {
        Ok(next.run(request).await)
    } else {
        Err(StatusCode::UNAUTHORIZED)
    }
}

let state = AppState {
    api_key: "secret-key".to_string(),
};

let app = Router::new()
    .route("/", get(|| async { "Protected" }))
    .layer(middleware::from_fn_with_state(state.clone(), require_api_key))
    .with_state(state);
```

## Modifying requests and responses

<Tabs>
  <Tab title="Modify request">
    Transform the request before it reaches handlers:

    ```rust theme={null}
    use axum::{
        extract::Request,
        middleware::Next,
        response::Response,
        http::header,
    };

    async fn add_request_id(
        mut request: Request,
        next: Next,
    ) -> Response {
        // Add a custom header to the request
        let request_id = uuid::Uuid::new_v4().to_string();
        request.headers_mut().insert(
            header::HeaderName::from_static("x-request-id"),
            request_id.parse().unwrap(),
        );
        
        next.run(request).await
    }
    ```
  </Tab>

  <Tab title="Modify response">
    Transform the response before sending to client:

    ```rust theme={null}
    use axum::{
        extract::Request,
        middleware::Next,
        response::Response,
        http::header,
    };

    async fn add_security_headers(
        request: Request,
        next: Next,
    ) -> Response {
        let mut response = next.run(request).await;
        
        // Add security headers
        let headers = response.headers_mut();
        headers.insert(
            header::HeaderName::from_static("x-content-type-options"),
            "nosniff".parse().unwrap(),
        );
        headers.insert(
            header::HeaderName::from_static("x-frame-options"),
            "DENY".parse().unwrap(),
        );
        
        response
    }
    ```
  </Tab>

  <Tab title="Read request body">
    Buffer and inspect the request body:

    ```rust theme={null}
    use axum::{
        body::{Body, Bytes},
        extract::Request,
        middleware::Next,
        response::{Response, IntoResponse},
        http::StatusCode,
    };
    use http_body_util::BodyExt;

    async fn print_request_body(
        request: Request,
        next: Next,
    ) -> Result<Response, StatusCode> {
        let (parts, body) = request.into_parts();
        
        // Buffer the body
        let bytes = body
            .collect()
            .await
            .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?
            .to_bytes();
        
        // Log the body
        if let Ok(body_str) = std::str::from_utf8(&bytes) {
            println!("Request body: {}", body_str);
        }
        
        // Reconstruct the request with the buffered body
        let request = Request::from_parts(parts, Body::from(bytes));
        
        Ok(next.run(request).await)
    }
    ```
  </Tab>
</Tabs>

## Layer ordering

<Warning>
  Middleware layers are applied in reverse order. The last layer added is executed first.
</Warning>

```rust theme={null}
use axum::{
    Router,
    routing::get,
    middleware::{self, Next},
    extract::Request,
    response::Response,
};

async fn first_middleware(request: Request, next: Next) -> Response {
    println!("First: before");
    let response = next.run(request).await;
    println!("First: after");
    response
}

async fn second_middleware(request: Request, next: Next) -> Response {
    println!("Second: before");
    let response = next.run(request).await;
    println!("Second: after");
    response
}

let app = Router::new()
    .route("/", get(|| async { "Handler" }))
    .layer(middleware::from_fn(first_middleware))
    .layer(middleware::from_fn(second_middleware));

// Execution order:
// 1. Second: before
// 2. First: before  
// 3. Handler
// 4. First: after
// 5. Second: after
```

## Tower middleware

Use any Tower middleware with Axum:

```rust theme={null}
use axum::Router;
use tower::ServiceBuilder;
use tower_http::{
    trace::TraceLayer,
    compression::CompressionLayer,
    timeout::TimeoutLayer,
};
use std::time::Duration;

let app = Router::new()
    .layer(
        ServiceBuilder::new()
            .layer(TraceLayer::new_for_http())
            .layer(CompressionLayer::new())
            .layer(TimeoutLayer::new(Duration::from_secs(10)))
    );
```

## Route-specific middleware

Apply middleware to specific routes:

```rust theme={null}
use axum::{
    Router,
    routing::get,
    middleware,
};

async fn admin_only(
    request: axum::extract::Request,
    next: axum::middleware::Next,
) -> axum::response::Response {
    // Check admin permissions...
    next.run(request).await
}

let app = Router::new()
    .route("/public", get(|| async { "Public" }))
    .route(
        "/admin",
        get(|| async { "Admin" })
            .layer(middleware::from_fn(admin_only))
    );
```

Alternatively, use `route_layer`:

```rust theme={null}
use axum::{
    Router,
    routing::get,
    middleware,
};

let app = Router::new()
    .route("/admin/users", get(|| async { "Users" }))
    .route("/admin/settings", get(|| async { "Settings" }))
    .route_layer(middleware::from_fn(admin_only))
    .route("/public", get(|| async { "Public" }));

async fn admin_only(
    request: axum::extract::Request,
    next: axum::middleware::Next,
) -> axum::response::Response {
    next.run(request).await
}

// admin_only only applies to routes added before route_layer
```

## Common middleware patterns

<Accordion title="Request logging">
  ```rust theme={null}
  use axum::{
      extract::Request,
      middleware::Next,
      response::Response,
  };

  async fn logging_middleware(
      request: Request,
      next: Next,
  ) -> Response {
      let method = request.method().clone();
      let uri = request.uri().clone();
      
      let start = std::time::Instant::now();
      let response = next.run(request).await;
      let duration = start.elapsed();
      
      println!(
          "{} {} - {} ({:?})",
          method,
          uri,
          response.status(),
          duration
      );
      
      response
  }
  ```
</Accordion>

<Accordion title="CORS headers">
  ```rust theme={null}
  use axum::{
      extract::Request,
      middleware::Next,
      response::Response,
      http::header,
  };

  async fn cors_middleware(
      request: Request,
      next: Next,
  ) -> Response {
      let mut response = next.run(request).await;
      
      let headers = response.headers_mut();
      headers.insert(
          header::ACCESS_CONTROL_ALLOW_ORIGIN,
          "*".parse().unwrap(),
      );
      headers.insert(
          header::ACCESS_CONTROL_ALLOW_METHODS,
          "GET, POST, PUT, DELETE".parse().unwrap(),
      );
      
      response
  }
  ```

  <Tip>
    For production, use the `tower-http` CORS layer instead.
  </Tip>
</Accordion>

## Error handling in middleware

Handle middleware errors appropriately:

```rust theme={null}
use axum::{
    extract::Request,
    middleware::Next,
    response::{Response, IntoResponse},
    http::StatusCode,
};

async fn fallible_middleware(
    request: Request,
    next: Next,
) -> Result<Response, StatusCode> {
    // Validate something that might fail
    if !is_valid(&request) {
        return Err(StatusCode::BAD_REQUEST);
    }
    
    Ok(next.run(request).await)
}

fn is_valid(_request: &Request) -> bool {
    true
}
```

## Next steps

<CardGroup cols={2}>
  <Card title="Error Handling" icon="triangle-exclamation" href="/concepts/error-handling">
    Learn how to handle errors from middleware
  </Card>

  <Card title="State" icon="database" href="/concepts/state">
    Use state in your middleware
  </Card>
</CardGroup>
