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

# OriginalUri

> Extract the original request URI regardless of nesting

`OriginalUri` is an extractor that provides the original request URI, even when the service is nested or the URI has been modified by middleware.

## Basic usage

```rust theme={null}
use axum::{
    Router,
    routing::get,
    extract::OriginalUri,
    http::Uri,
};

let api_routes = Router::new().route(
    "/users",
    get(|uri: Uri, OriginalUri(original_uri): OriginalUri| async move {
        // uri is "/users"
        // original_uri is "/api/users"
        format!("URI: {}, Original: {}", uri, original_uri)
    })
);

let app = Router::new().nest("/api", api_routes);
```

## Difference from Uri

When using nested services, the regular `Uri` extractor has the nesting prefix stripped, while `OriginalUri` preserves it:

```rust theme={null}
use axum::{Router, routing::get, extract::OriginalUri, http::Uri};

async fn show_uris(uri: Uri, OriginalUri(original): OriginalUri) -> String {
    format!("Nested URI: {}\nOriginal URI: {}", uri.path(), original.path())
}

let api = Router::new().route("/users", get(show_uris));
let app = Router::new().nest("/api/v1", api);

// Request to /api/v1/users:
// Nested URI: /users
// Original URI: /api/v1/users
```

## Using in middleware

`OriginalUri` can be accessed from middleware via request extensions:

```rust theme={null}
use axum::{
    Router,
    routing::get,
    extract::OriginalUri,
    http::Request,
};
use tower_http::trace::TraceLayer;

let api_routes = Router::new()
    .route("/users/{id}", get(|| async { /* ... */ }))
    .layer(
        TraceLayer::new_for_http().make_span_with(|req: &Request<_>| {
            let path = if let Some(original_uri) = req.extensions().get::<OriginalUri>() {
                // This will include /api prefix
                original_uri.0.path().to_owned()
            } else {
                req.uri().path().to_owned()
            };
            tracing::info_span!("http-request", %path)
        })
    );

let app = Router::new().nest("/api", api_routes);
```

## When to use OriginalUri

<Info>
  Use `OriginalUri` when you need the full path as it was originally requested, especially in nested services or when middleware modifies the URI.
</Info>

### Use cases

* **Logging the full request path**: Track complete URLs in nested services
* **Redirects**: Generate redirect URLs based on the original request
* **Authentication**: Check the full path against access control lists
* **Middleware that modifies URIs**: Access the pre-modification URI

## Type signature

`OriginalUri` is a tuple struct containing a `Uri`:

<ParamField path="0" type="Uri">
  The original HTTP URI from the request.
</ParamField>

## Deref behavior

`OriginalUri` implements `Deref<Target = Uri>`, so you can call `Uri` methods directly:

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

async fn handler(original: OriginalUri) -> String {
    // Can call Uri methods directly
    let path = original.path();
    let query = original.query();
    
    format!("Path: {}, Query: {:?}", path, query)
}

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

## Rejection

`OriginalUri` is infallible - it will always succeed. If no `OriginalUri` extension exists, it falls back to the current request URI.

<Note>
  The `OriginalUri` extension is automatically added by Axum's router for all requests. It will only be missing if another extractor or middleware has removed it.
</Note>

## Example: Full path logging in nested routers

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

async fn log_request(req: Request, next: Next) -> Response {
    if let Some(OriginalUri(uri)) = req.extensions().get::<OriginalUri>() {
        println!("Incoming request: {} {}", req.method(), uri);
    }
    next.run(req).await
}

let v1_routes = Router::new()
    .route("/users", get(|| async { "V1 users" }))
    .layer(middleware::from_fn(log_request));

let v2_routes = Router::new()
    .route("/users", get(|| async { "V2 users" }))
    .layer(middleware::from_fn(log_request));

let app = Router::new()
    .nest("/api/v1", v1_routes)
    .nest("/api/v2", v2_routes);

// Request to /api/v1/users logs: "Incoming request: GET /api/v1/users"
// Without OriginalUri, it would log: "Incoming request: GET /users"
```

## See also

* [Uri](/api/extractors/uri) - Extract the current request URI (may be modified by nesting)
* [MatchedPath](/api/extractors/matched-path) - Extract the route pattern that matched
