axum 0.3.1

Web framework that focuses on ergonomics and modularity
Documentation
Add another route to the router.

`path` is a string of path segments separated by `/`. Each segment
can be either static, a capture, or a wildcard.

`service` is the [`Service`] that should receive the request if the path matches
`path`. `service` will commonly be a handler wrapped in a method router like
[`get`](crate::routing::get). See [`handler`](crate::handler) for more details
on handlers.

# Static paths

Examples:

- `/`
- `/foo`
- `/users/123`

If the incoming request matches the path exactly the corresponding service will
be called.

# Captures

Paths can contain segments like `/:key` which matches any single segment and
will store the value captured at `key`.

Examples:

- `/:key`
- `/users/:id`
- `/users/:id/tweets`

Captures can be extracted using [`Path`](crate::extract::Path). See its
documentation for more details.

It is not possible to create segments that only match some types like numbers or
regular expression. You must handle that manually in your handlers.

[`MatchedPath`](crate::extract::MatchedPath) can be used to extract the matched
path rather than the actual path.

# Wildcards

Paths can end in `/*key` which matches all segments and will store the segments
captured at `key`.

Examples:

- `/*key`
- `/assets/*path`
- `/:id/:repo/*tree`

Wildcard captures can also be extracted using [`Path`](crate::extract::Path).

# More examples

```rust
use axum::{Router, routing::{get, delete}, extract::Path};

let app = Router::new()
    .route("/", get(root))
    .route("/users", get(list_users).post(create_user))
    .route("/users/:id", get(show_user))
    .route("/api/:version/users/:id/action", delete(do_users_action))
    .route("/assets/*path", get(serve_asset));

async fn root() {}

async fn list_users() {}

async fn create_user() {}

async fn show_user(Path(id): Path<u64>) {}

async fn do_users_action(Path((version, id)): Path<(String, u64)>) {}

async fn serve_asset(Path(path): Path<String>) {}
# async {
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
# };
```

# Routing to any [`Service`]

axum also supports routing to general [`Service`]s:

```rust,no_run
use axum::{
    Router,
    body::Body,
    routing::service_method_routing as service,
    error_handling::HandleErrorExt,
    http::{Request, StatusCode},
};
use tower_http::services::ServeFile;
use http::Response;
use std::{convert::Infallible, io};
use tower::service_fn;

let app = Router::new()
    .route(
        // Any request to `/` goes to a service
        "/",
        // Services whose response body is not `axum::body::BoxBody`
        // can be wrapped in `axum::service::any` (or one of the other routing filters)
        // to have the response body mapped
        service::any(service_fn(|_: Request<Body>| async {
            let res = Response::new(Body::from("Hi from `GET /`"));
            Ok::<_, Infallible>(res)
        }))
    )
    .route(
        "/foo",
        // This service's response body is `axum::body::BoxBody` so
        // it can be routed to directly.
        service_fn(|req: Request<Body>| async move {
            let body = Body::from(format!("Hi from `{} /foo`", req.method()));
            let body = axum::body::box_body(body);
            let res = Response::new(body);
            Ok::<_, Infallible>(res)
        })
    )
    .route(
        // GET `/static/Cargo.toml` goes to a service from tower-http
        "/static/Cargo.toml",
        service::get(ServeFile::new("Cargo.toml"))
            // though we must handle any potential errors
            .handle_error(|error: io::Error| {
                (
                    StatusCode::INTERNAL_SERVER_ERROR,
                    format!("Unhandled internal error: {}", error),
                )
            })
    );
# async {
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
# };
```

Routing to arbitrary services in this way has complications for backpressure
([`Service::poll_ready`]). See the [`service_method_routing`] module for more
details.

# Panics

Panics if the route overlaps with another route:

```rust,should_panic
use axum::{routing::get, Router};

let app = Router::new()
    .route("/", get(|| async {}))
    .route("/", get(|| async {}));
# async {
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
# };
```

The static route `/foo` and the dynamic route `/:key` are not considered to
overlap and `/foo` will take precedence.

Take care when using [`Router::nest`] as it behaves like a wildcard route.
Therefore this setup panics:

```rust,should_panic
use axum::{routing::get, Router};

let app = Router::new()
    // this is similar to `/api/*`
    .nest("/api", get(|| async {}))
    // which overlaps with this route
    .route("/api/users", get(|| async {}));
# async {
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
# };
```

Also panics if `path` is empty.

## Nesting

`route` cannot be used to nest `Router`s. Instead use [`Router::nest`].

Attempting to will result in a panic:

```rust,should_panic
use axum::{routing::get, Router};

let app = Router::new().route(
    "/",
    Router::new().route("/foo", get(|| async {})),
);
# async {
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
# };
```