> ## 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.

# Extension

> Extract and insert typed values in request/response extensions

`Extension<T>` is both an extractor and a response type that works with HTTP extensions to share state across handlers and middleware.

## As an extractor

`Extension` allows handlers to extract values that have been added to request extensions by middleware or layers:

```rust theme={null}
use axum::{Router, routing::get, Extension};
use std::sync::Arc;

#[derive(Clone)]
struct State {
    count: i32,
}

async fn handler(Extension(state): Extension<Arc<State>>) -> String {
    format!("Count: {}", state.count)
}

let state = Arc::new(State { count: 42 });

let app = Router::new()
    .route("/", get(handler))
    .layer(Extension(state));
```

### Optional extensions

If an extension might not be present, use `Option<Extension<T>>`:

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

#[derive(Clone)]
struct Config {
    debug: bool,
}

async fn handler(config: Option<Extension<Config>>) -> String {
    match config {
        Some(Extension(cfg)) => format!("Debug: {}", cfg.debug),
        None => "No config available".to_string(),
    }
}

let app = Router::new().route("/", get(handler));
```

<Warning>
  If you extract `Extension<T>` (without `Option`) and the extension is missing, the request will be rejected with a `500 Internal Server Error`.
</Warning>

## As a layer

`Extension` can be used as a layer to add values to all requests:

```rust theme={null}
use axum::{Router, routing::get, Extension};
use std::sync::Arc;

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

let config = Arc::new(AppConfig {
    api_key: "secret".to_string(),
});

let app = Router::new()
    .route("/", get(|| async { "Hello" }))
    .layer(Extension(config));
```

## As a response

`Extension` can be returned from handlers to add values to response extensions:

```rust theme={null}
use axum::{
    Router,
    routing::get,
    Extension,
    response::IntoResponse,
};

#[derive(Clone)]
struct Metadata {
    request_id: String,
}

async fn handler() -> impl IntoResponse {
    (
        Extension(Metadata {
            request_id: "abc-123".to_string(),
        }),
        "Response body"
    )
}

let app = Router::new().route("/", get(handler));
```

## Extension vs State

`Extension` and `State` are similar but have important differences:

| Feature             | Extension                     | State                        |
| ------------------- | ----------------------------- | ---------------------------- |
| **Type safety**     | No compile-time checks        | Type checked at compile time |
| **Multiple values** | Can have many different types | One state type per router    |
| **Added via**       | Middleware/layer              | `with_state()`               |
| **Recommended for** | Middleware-injected data      | Application state            |

```rust theme={null}
use axum::{Router, routing::get, Extension, extract::State};
use std::sync::Arc;

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

#[derive(Clone)]
struct RequestId(String);

// State: defined when creating the router
async fn with_state(State(state): State<Arc<AppState>>) -> String {
    format!("DB: {}", state.db)
}

// Extension: added by middleware
async fn with_extension(Extension(id): Extension<RequestId>) -> String {
    format!("Request ID: {}", id.0)
}

let state = Arc::new(AppState { db: "postgres".to_string() });

let app = Router::new()
    .route("/state", get(with_state))
    .route("/extension", get(with_extension))
    .layer(Extension(RequestId("req-123".to_string())))
    .with_state(state);
```

<Info>
  Prefer `State` for application-level state that's known at compile time. Use `Extension` for values added by middleware or for multiple independent shared values.
</Info>

## Type requirements

The type `T` in `Extension<T>` must be:

* `Clone` - Values are cloned when extracted
* `Send + Sync` - Required for async handlers
* `'static` - Cannot contain non-static references

```rust theme={null}
use axum::Extension;
use std::sync::Arc;

// ✅ Good: Arc for shared ownership
#[derive(Clone)]
struct Good {
    data: Arc<String>,
}

// ❌ Bad: Contains non-static reference
// #[derive(Clone)]
// struct Bad<'a> {
//     data: &'a str,
// }
```

## Rejection

Rejects with `MissingExtension` when:

* The extension type wasn't added via layer or middleware
* A previous extractor removed it from request extensions

Error message:

```
Extension of type `your::Type` was not found. Perhaps you forgot to add it? See `axum::Extension`.
```

## Example: Request ID middleware

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

#[derive(Clone)]
struct RequestId(String);

async fn add_request_id(mut req: Request, next: Next) -> Response {
    let id = RequestId(Uuid::new_v4().to_string());
    req.extensions_mut().insert(id);
    next.run(req).await
}

async fn handler(Extension(RequestId(id)): Extension<RequestId>) -> String {
    format!("Your request ID: {}", id)
}

let app = Router::new()
    .route("/", get(handler))
    .layer(middleware::from_fn(add_request_id));
```

## See also

* [State](/api/extractors/state) - Recommended way to share application state
* [ConnectInfo](/api/extractors/connect-info) - Extract connection metadata
