Struct tonic::service::AxumRouter

source ·
pub struct AxumRouter<S = ()> { /* private fields */ }
Expand description

The router type for composing handlers and services.

Implementations§

source§

impl<S> Router<S>
where S: Clone + Send + Sync + 'static,

source

pub fn new() -> Router<S>

Create a new Router.

Unless you add additional routes this will respond with 404 Not Found to all requests.

source

pub fn route(self, path: &str, method_router: MethodRouter<S>) -> Router<S>

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.

method_router is the MethodRouter that should receive the request if the path matches path. method_router will commonly be a handler wrapped in a method router like get. See 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. The value captured can be zero-length except for in the invalid path //.

Examples:

  • /:key
  • /users/:id
  • /users/:id/tweets

Captures can be extracted using 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 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

Note that /*key doesn’t match empty segments. Thus:

  • /*key doesn’t match / but does match /a, /a/, etc.
  • /x/*key doesn’t match /x or /x/ but does match /x/a, /x/a/, etc.

Wildcard captures can also be extracted using Path:

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

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

async fn handler(Path(path): Path<String>) -> String {
    path
}

Note that the leading slash is not included, i.e. for the route /foo/*rest and the path /foo/bar/baz the value of rest will be bar/baz.

§Accepting multiple methods

To accept multiple methods for the same route you can add all handlers at the same time:

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

let app = Router::new().route(
    "/",
    get(get_root).post(post_root).delete(delete_root),
);

async fn get_root() {}

async fn post_root() {}

async fn delete_root() {}

Or you can add them one by one:

let app = Router::new()
    .route("/", get(get_root))
    .route("/", post(post_root))
    .route("/", delete(delete_root));
§More examples
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>) {}
§Panics

Panics if the route overlaps with another route:

use axum::{routing::get, Router};

let app = Router::new()
    .route("/", get(|| async {}))
    .route("/", get(|| async {}));

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

Also panics if path is empty.

source

pub fn route_service<T>(self, path: &str, service: T) -> Router<S>
where T: Service<Request<Body>, Error = Infallible> + Clone + Send + 'static, <T as Service<Request<Body>>>::Response: IntoResponse, <T as Service<Request<Body>>>::Future: Send + 'static,

Add another route to the router that calls a Service.

§Example
use axum::{
    Router,
    body::Body,
    routing::{any_service, get_service},
    extract::Request,
    http::StatusCode,
    error_handling::HandleErrorLayer,
};
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::routing::any_service` (or one of the other routing filters)
        // to have the response body mapped
        any_service(service_fn(|_: Request| async {
            let res = Response::new(Body::from("Hi from `GET /`"));
            Ok::<_, Infallible>(res)
        }))
    )
    .route_service(
        "/foo",
        // This service's response body is `axum::body::BoxBody` so
        // it can be routed to directly.
        service_fn(|req: Request| async move {
            let body = Body::from(format!("Hi from `{} /foo`", req.method()));
            let res = Response::new(body);
            Ok::<_, Infallible>(res)
        })
    )
    .route_service(
        // GET `/static/Cargo.toml` goes to a service from tower-http
        "/static/Cargo.toml",
        ServeFile::new("Cargo.toml"),
    );

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

§Panics

Panics for the same reasons as Router::route or if you attempt to route to a Router:

use axum::{routing::get, Router};

let app = Router::new().route_service(
    "/",
    Router::new().route("/foo", get(|| async {})),
);

Use Router::nest instead.

source

pub fn nest(self, path: &str, router: Router<S>) -> Router<S>

Nest a Router at some path.

This allows you to break your application into smaller pieces and compose them together.

§Example
use axum::{
    routing::{get, post},
    Router,
};

let user_routes = Router::new().route("/:id", get(|| async {}));

let team_routes = Router::new().route("/", post(|| async {}));

let api_routes = Router::new()
    .nest("/users", user_routes)
    .nest("/teams", team_routes);

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

// Our app now accepts
// - GET /api/users/:id
// - POST /api/teams
§How the URI changes

Note that nested routes will not see the original request URI but instead have the matched prefix stripped. This is necessary for services like static file serving to work. Use OriginalUri if you need the original request URI.

§Captures from outer routes

Take care when using nest together with dynamic routes as nesting also captures from the outer routes:

use axum::{
    extract::Path,
    routing::get,
    Router,
};
use std::collections::HashMap;

async fn users_get(Path(params): Path<HashMap<String, String>>) {
    // Both `version` and `id` were captured even though `users_api` only
    // explicitly captures `id`.
    let version = params.get("version");
    let id = params.get("id");
}

let users_api = Router::new().route("/users/:id", get(users_get));

let app = Router::new().nest("/:version/api", users_api);
§Differences from wildcard routes

Nested routes are similar to wildcard routes. The difference is that wildcard routes still see the whole URI whereas nested routes will have the prefix stripped:

use axum::{routing::get, http::Uri, Router};

let nested_router = Router::new()
    .route("/", get(|uri: Uri| async {
        // `uri` will _not_ contain `/bar`
    }));

let app = Router::new()
    .route("/foo/*rest", get(|uri: Uri| async {
        // `uri` will contain `/foo`
    }))
    .nest("/bar", nested_router);

Additionally, while the wildcard route /foo/*rest will not match the paths /foo or /foo/, a nested router at /foo will match the path /foo (but not /foo/), and a nested router at /foo/ will match the path /foo/ (but not /foo).

§Fallbacks

If a nested router doesn’t have its own fallback then it will inherit the fallback from the outer router:

use axum::{routing::get, http::StatusCode, handler::Handler, Router};

async fn fallback() -> (StatusCode, &'static str) {
    (StatusCode::NOT_FOUND, "Not Found")
}

let api_routes = Router::new().route("/users", get(|| async {}));

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

Here requests like GET /api/not-found will go into api_routes but because it doesn’t have a matching route and doesn’t have its own fallback it will call the fallback from the outer router, i.e. the fallback function.

If the nested router has its own fallback then the outer fallback will not be inherited:

use axum::{
    routing::get,
    http::StatusCode,
    handler::Handler,
    Json,
    Router,
};

async fn fallback() -> (StatusCode, &'static str) {
    (StatusCode::NOT_FOUND, "Not Found")
}

async fn api_fallback() -> (StatusCode, Json<serde_json::Value>) {
    (
        StatusCode::NOT_FOUND,
        Json(serde_json::json!({ "status": "Not Found" })),
    )
}

let api_routes = Router::new()
    .route("/users", get(|| async {}))
    .fallback(api_fallback);

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

Here requests like GET /api/not-found will go to api_fallback.

§Nesting routers with state

When combining Routers with this method, each Router must have the same type of state. If your routers have different types you can use Router::with_state to provide the state and make the types match:

use axum::{
    Router,
    routing::get,
    extract::State,
};

#[derive(Clone)]
struct InnerState {}

#[derive(Clone)]
struct OuterState {}

async fn inner_handler(state: State<InnerState>) {}

let inner_router = Router::new()
    .route("/bar", get(inner_handler))
    .with_state(InnerState {});

async fn outer_handler(state: State<OuterState>) {}

let app = Router::new()
    .route("/", get(outer_handler))
    .nest("/foo", inner_router)
    .with_state(OuterState {});

Note that the inner router will still inherit the fallback from the outer router.

§Panics
  • If the route overlaps with another route. See Router::route for more details.
  • If the route contains a wildcard (*).
  • If path is empty.
source

pub fn nest_service<T>(self, path: &str, service: T) -> Router<S>
where T: Service<Request<Body>, Error = Infallible> + Clone + Send + 'static, <T as Service<Request<Body>>>::Response: IntoResponse, <T as Service<Request<Body>>>::Future: Send + 'static,

Like nest, but accepts an arbitrary Service.

source

pub fn merge<R>(self, other: R) -> Router<S>
where R: Into<Router<S>>,

Merge the paths and fallbacks of two routers into a single Router.

This is useful for breaking apps into smaller pieces and combining them into one.

use axum::{
    routing::get,
    Router,
};

// define some routes separately
let user_routes = Router::new()
    .route("/users", get(users_list))
    .route("/users/:id", get(users_show));

let team_routes = Router::new()
    .route("/teams", get(teams_list));

// combine them into one
let app = Router::new()
    .merge(user_routes)
    .merge(team_routes);

// could also do `user_routes.merge(team_routes)`

// Our app now accepts
// - GET /users
// - GET /users/:id
// - GET /teams
§Merging routers with state

When combining Routers with this method, each Router must have the same type of state. If your routers have different types you can use Router::with_state to provide the state and make the types match:

use axum::{
    Router,
    routing::get,
    extract::State,
};

#[derive(Clone)]
struct InnerState {}

#[derive(Clone)]
struct OuterState {}

async fn inner_handler(state: State<InnerState>) {}

let inner_router = Router::new()
    .route("/bar", get(inner_handler))
    .with_state(InnerState {});

async fn outer_handler(state: State<OuterState>) {}

let app = Router::new()
    .route("/", get(outer_handler))
    .merge(inner_router)
    .with_state(OuterState {});
§Merging routers with fallbacks

When combining Routers with this method, the fallback is also merged. However only one of the routers can have a fallback.

§Panics
  • If two routers that each have a fallback are merged. This is because Router only allows a single fallback.
source

pub fn layer<L>(self, layer: L) -> Router<S>
where L: Layer<Route> + Clone + Send + 'static, <L as Layer<Route>>::Service: Service<Request<Body>> + Clone + Send + 'static, <<L as Layer<Route>>::Service as Service<Request<Body>>>::Response: IntoResponse + 'static, <<L as Layer<Route>>::Service as Service<Request<Body>>>::Error: Into<Infallible> + 'static, <<L as Layer<Route>>::Service as Service<Request<Body>>>::Future: Send + 'static,

Apply a tower::Layer to all routes in the router.

This can be used to add additional processing to a request for a group of routes.

Note that the middleware is only applied to existing routes. So you have to first add your routes (and / or fallback) and then call layer afterwards. Additional routes added after layer is called will not have the middleware added.

If you want to add middleware to a single handler you can either use MethodRouter::layer or Handler::layer.

§Example

Adding the [tower_http::trace::TraceLayer]:

use axum::{routing::get, Router};
use tower_http::trace::TraceLayer;

let app = Router::new()
    .route("/foo", get(|| async {}))
    .route("/bar", get(|| async {}))
    .layer(TraceLayer::new_for_http());

If you need to write your own middleware see “Writing middleware” for the different options.

If you only want middleware on some routes you can use Router::merge:

use axum::{routing::get, Router};
use tower_http::{trace::TraceLayer, compression::CompressionLayer};

let with_tracing = Router::new()
    .route("/foo", get(|| async {}))
    .layer(TraceLayer::new_for_http());

let with_compression = Router::new()
    .route("/bar", get(|| async {}))
    .layer(CompressionLayer::new());

// Merge everything into one `Router`
let app = Router::new()
    .merge(with_tracing)
    .merge(with_compression);
§Multiple middleware

It’s recommended to use tower::ServiceBuilder when applying multiple middleware. See middleware for more details.

§Runs after routing

Middleware added with this method will run after routing and thus cannot be used to rewrite the request URI. See “Rewriting request URI in middleware” for more details and a workaround.

§Error handling

See middleware for details on how error handling impacts middleware.

source

pub fn route_layer<L>(self, layer: L) -> Router<S>
where L: Layer<Route> + Clone + Send + 'static, <L as Layer<Route>>::Service: Service<Request<Body>> + Clone + Send + 'static, <<L as Layer<Route>>::Service as Service<Request<Body>>>::Response: IntoResponse + 'static, <<L as Layer<Route>>::Service as Service<Request<Body>>>::Error: Into<Infallible> + 'static, <<L as Layer<Route>>::Service as Service<Request<Body>>>::Future: Send + 'static,

Apply a tower::Layer to the router that will only run if the request matches a route.

Note that the middleware is only applied to existing routes. So you have to first add your routes (and / or fallback) and then call route_layer afterwards. Additional routes added after route_layer is called will not have the middleware added.

This works similarly to Router::layer except the middleware will only run if the request matches a route. This is useful for middleware that return early (such as authorization) which might otherwise convert a 404 Not Found into a 401 Unauthorized.

This function will panic if no routes have been declared yet on the router, since the new layer will have no effect, and this is typically a bug. In generic code, you can test if that is the case first, by calling Router::has_routes.

§Example
use axum::{
    routing::get,
    Router,
};
use tower_http::validate_request::ValidateRequestHeaderLayer;

let app = Router::new()
    .route("/foo", get(|| async {}))
    .route_layer(ValidateRequestHeaderLayer::bearer("password"));

// `GET /foo` with a valid token will receive `200 OK`
// `GET /foo` with a invalid token will receive `401 Unauthorized`
// `GET /not-found` with a invalid token will receive `404 Not Found`
source

pub fn has_routes(&self) -> bool

True if the router currently has at least one route added.

source

pub fn fallback<H, T>(self, handler: H) -> Router<S>
where H: Handler<T, S>, T: 'static,

Add a fallback Handler to the router.

This service will be called if no routes matches the incoming request.

use axum::{
    Router,
    routing::get,
    handler::Handler,
    response::IntoResponse,
    http::{StatusCode, Uri},
};

let app = Router::new()
    .route("/foo", get(|| async { /* ... */ }))
    .fallback(fallback);

async fn fallback(uri: Uri) -> (StatusCode, String) {
    (StatusCode::NOT_FOUND, format!("No route for {uri}"))
}

Fallbacks only apply to routes that aren’t matched by anything in the router. If a handler is matched by a request but returns 404 the fallback is not called. Note that this applies to MethodRouters too: if the request hits a valid path but the MethodRouter does not have an appropriate method handler installed, the fallback is not called (use MethodRouter::fallback for this purpose instead).

§Handling all requests without other routes

Using Router::new().fallback(...) to accept all request regardless of path or method, if you don’t have other routes, isn’t optimal:

use axum::Router;

async fn handler() {}

let app = Router::new().fallback(handler);

let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();

Running the handler directly is faster since it avoids the overhead of routing:

use axum::handler::HandlerWithoutStateExt;

async fn handler() {}

let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, handler.into_make_service()).await.unwrap();
source

pub fn fallback_service<T>(self, service: T) -> Router<S>
where T: Service<Request<Body>, Error = Infallible> + Clone + Send + 'static, <T as Service<Request<Body>>>::Response: IntoResponse, <T as Service<Request<Body>>>::Future: Send + 'static,

Add a fallback Service to the router.

See Router::fallback for more details.

source

pub fn with_state<S2>(self, state: S) -> Router<S2>

Provide the state for the router.

use axum::{Router, routing::get, extract::State};

#[derive(Clone)]
struct AppState {}

let routes = Router::new()
    .route("/", get(|State(state): State<AppState>| async {
        // use state
    }))
    .with_state(AppState {});

let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, routes).await.unwrap();
§Returning routers with states from functions

When returning Routers from functions, it is generally recommended not to set the state directly:

use axum::{Router, routing::get, extract::State};

#[derive(Clone)]
struct AppState {}

// Don't call `Router::with_state` here
fn routes() -> Router<AppState> {
    Router::new()
        .route("/", get(|_: State<AppState>| async {}))
}

// Instead do it before you run the server
let routes = routes().with_state(AppState {});

let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, routes).await.unwrap();

If you do need to provide the state, and you’re not nesting/merging the router into another router, then return Router without any type parameters:

// Don't return `Router<AppState>`
fn routes(state: AppState) -> Router {
    Router::new()
        .route("/", get(|_: State<AppState>| async {}))
        .with_state(state)
}

let routes = routes(AppState {});

let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, routes).await.unwrap();

This is because we can only call Router::into_make_service on Router<()>, not Router<AppState>. See below for more details about why that is.

Note that the state defaults to () so Router and Router<()> is the same.

If you are nesting/merging the router it is recommended to use a generic state type on the resulting router:

fn routes<S>(state: AppState) -> Router<S> {
    Router::new()
        .route("/", get(|_: State<AppState>| async {}))
        .with_state(state)
}

let routes = Router::new().nest("/api", routes(AppState {}));

let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, routes).await.unwrap();
§State is global within the router

The state passed to this method will be used for all requests this router receives. That means it is not suitable for holding state derived from a request, such as authorization data extracted in a middleware. Use Extension instead for such data.

§What S in Router<S> means

Router<S> means a router that is missing a state of type S to be able to handle requests. It does not mean a Router that has a state of type S.

For example:

// A router that _needs_ an `AppState` to handle requests
let router: Router<AppState> = Router::new()
    .route("/", get(|_: State<AppState>| async {}));

// Once we call `Router::with_state` the router isn't missing
// the state anymore, because we just provided it
//
// Therefore the router type becomes `Router<()>`, i.e a router
// that is not missing any state
let router: Router<()> = router.with_state(AppState {});

// Only `Router<()>` has the `into_make_service` method.
//
// You cannot call `into_make_service` on a `Router<AppState>`
// because it is still missing an `AppState`.
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, router).await.unwrap();

Perhaps a little counter intuitively, Router::with_state doesn’t always return a Router<()>. Instead you get to pick what the new missing state type is:

let router: Router<AppState> = Router::new()
    .route("/", get(|_: State<AppState>| async {}));

// When we call `with_state` we're able to pick what the next missing state type is.
// Here we pick `String`.
let string_router: Router<String> = router.with_state(AppState {});

// That allows us to add new routes that uses `String` as the state type
let string_router = string_router
    .route("/needs-string", get(|_: State<String>| async {}));

// Provide the `String` and choose `()` as the new missing state.
let final_router: Router<()> = string_router.with_state("foo".to_owned());

// Since we have a `Router<()>` we can run it.
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, final_router).await.unwrap();

This why this returning Router<AppState> after calling with_state doesn’t work:

// This won't work because we're returning a `Router<AppState>`
// i.e. we're saying we're still missing an `AppState`
fn routes(state: AppState) -> Router<AppState> {
    Router::new()
        .route("/", get(|_: State<AppState>| async {}))
        .with_state(state)
}

let app = routes(AppState {});

// We can only call `Router::into_make_service` on a `Router<()>`
// but `app` is a `Router<AppState>`
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();

Instead return Router<()> since we have provided all the state needed:

// We've provided all the state necessary so return `Router<()>`
fn routes(state: AppState) -> Router<()> {
    Router::new()
        .route("/", get(|_: State<AppState>| async {}))
        .with_state(state)
}

let app = routes(AppState {});

// We can now call `Router::into_make_service`
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
§A note about performance

If you need a Router that implements Service but you don’t need any state (perhaps you’re making a library that uses axum internally) then it is recommended to call this method before you start serving requests:

use axum::{Router, routing::get};

let app = Router::new()
    .route("/", get(|| async { /* ... */ }))
    // even though we don't need any state, call `with_state(())` anyway
    .with_state(());

This is not required but it gives axum a chance to update some internals in the router which may impact performance and reduce allocations.

Note that Router::into_make_service and Router::into_make_service_with_connect_info do this automatically.

source

pub fn as_service<B>(&mut self) -> RouterAsService<'_, B, S>

Convert the router into a borrowed Service with a fixed request body type, to aid type inference.

In some cases when calling methods from tower::ServiceExt on a Router you might get type inference errors along the lines of

let response = router.ready().await?.call(request).await?;
                      ^^^^^ cannot infer type for type parameter `B`

This happens because Router implements Service with impl<B> Service<Request<B>> for Router<()>.

For example:

use axum::{
    Router,
    routing::get,
    http::Request,
    body::Body,
};
use tower::{Service, ServiceExt};

let mut router = Router::new().route("/", get(|| async {}));
let request = Request::new(Body::empty());
let response = router.ready().await?.call(request).await?;

Calling Router::as_service fixes that:

use axum::{
    Router,
    routing::get,
    http::Request,
    body::Body,
};
use tower::{Service, ServiceExt};

let mut router = Router::new().route("/", get(|| async {}));
let request = Request::new(Body::empty());
let response = router.as_service().ready().await?.call(request).await?;

This is mainly used when calling Router in tests. It shouldn’t be necessary when running the Router normally via Router::into_make_service.

source

pub fn into_service<B>(self) -> RouterIntoService<B, S>

Convert the router into an owned Service with a fixed request body type, to aid type inference.

This is the same as Router::as_service instead it returns an owned Service. See that method for more details.

source§

impl Router

source

pub fn into_make_service(self) -> IntoMakeService<Router>

Convert this router into a MakeService, that is a Service whose response is another service.

use axum::{
    routing::get,
    Router,
};

let app = Router::new().route("/", get(|| async { "Hi!" }));

let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
source

pub fn into_make_service_with_connect_info<C>( self, ) -> IntoMakeServiceWithConnectInfo<Router, C>

Convert this router into a MakeService, that will store C’s associated ConnectInfo in a request extension such that ConnectInfo can extract it.

This enables extracting things like the client’s remote address.

Extracting std::net::SocketAddr is supported out of the box:

use axum::{
    extract::ConnectInfo,
    routing::get,
    Router,
};
use std::net::SocketAddr;

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

async fn handler(ConnectInfo(addr): ConnectInfo<SocketAddr>) -> String {
    format!("Hello {addr}")
}

let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app.into_make_service_with_connect_info::<SocketAddr>()).await.unwrap();

You can implement custom a Connected like so:

use axum::{
    extract::connect_info::{ConnectInfo, Connected},
    routing::get,
    serve::IncomingStream,
    Router,
};

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

async fn handler(
    ConnectInfo(my_connect_info): ConnectInfo<MyConnectInfo>,
) -> String {
    format!("Hello {my_connect_info:?}")
}

#[derive(Clone, Debug)]
struct MyConnectInfo {
    // ...
}

impl Connected<IncomingStream<'_>> for MyConnectInfo {
    fn connect_info(target: IncomingStream<'_>) -> Self {
        MyConnectInfo {
            // ...
        }
    }
}

let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app.into_make_service_with_connect_info::<MyConnectInfo>()).await.unwrap();

See the unix domain socket example for an example of how to use this to collect UDS connection info.

Trait Implementations§

source§

impl<S> Clone for Router<S>

source§

fn clone(&self) -> Router<S>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<S> Debug for Router<S>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
source§

impl<S> Default for Router<S>
where S: Clone + Send + Sync + 'static,

source§

fn default() -> Router<S>

Returns the “default value” for a type. Read more
source§

impl From<Router> for Routes

source§

fn from(router: Router) -> Self

Converts to this type from the input type.
source§

impl Service<IncomingStream<'_>> for Router

source§

type Response = Router

Responses given by the service.
source§

type Error = Infallible

Errors produced by the service.
source§

type Future = Ready<Result<<Router as Service<IncomingStream<'_>>>::Response, <Router as Service<IncomingStream<'_>>>::Error>>

The future response value.
source§

fn poll_ready( &mut self, _cx: &mut Context<'_>, ) -> Poll<Result<(), <Router as Service<IncomingStream<'_>>>::Error>>

Returns Poll::Ready(Ok(())) when the service is able to process requests. Read more
source§

fn call( &mut self, _req: IncomingStream<'_>, ) -> <Router as Service<IncomingStream<'_>>>::Future

Process the request and return the response asynchronously. Read more
source§

impl<B> Service<Request<B>> for Router
where B: Body<Data = Bytes> + Send + 'static, <B as Body>::Error: Into<Box<dyn Error + Sync + Send>>,

source§

type Response = Response<Body>

Responses given by the service.
source§

type Error = Infallible

Errors produced by the service.
source§

type Future = RouteFuture<Infallible>

The future response value.
source§

fn poll_ready( &mut self, _: &mut Context<'_>, ) -> Poll<Result<(), <Router as Service<Request<B>>>::Error>>

Returns Poll::Ready(Ok(())) when the service is able to process requests. Read more
source§

fn call(&mut self, req: Request<B>) -> <Router as Service<Request<B>>>::Future

Process the request and return the response asynchronously. Read more

Auto Trait Implementations§

§

impl<S> Freeze for Router<S>

§

impl<S = ()> !RefUnwindSafe for Router<S>

§

impl<S> Send for Router<S>

§

impl<S> Sync for Router<S>

§

impl<S> Unpin for Router<S>

§

impl<S = ()> !UnwindSafe for Router<S>

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit #126799)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> FromRef<T> for T
where T: Clone,

source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
source§

impl<T, ReqBody, ResBody> GrpcService<ReqBody> for T
where T: Service<Request<ReqBody>, Response = Response<ResBody>>, <T as Service<Request<ReqBody>>>::Error: Into<Box<dyn Error + Sync + Send>>, ResBody: Body, <ResBody as Body>::Error: Into<Box<dyn Error + Sync + Send>>,

source§

type ResponseBody = ResBody

Responses body given by the service.
source§

type Error = <T as Service<Request<ReqBody>>>::Error

Errors produced by the service.
source§

type Future = <T as Service<Request<ReqBody>>>::Future

The future response value.
source§

fn poll_ready( &mut self, cx: &mut Context<'_>, ) -> Poll<Result<(), <T as GrpcService<ReqBody>>::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call( &mut self, request: Request<ReqBody>, ) -> <T as GrpcService<ReqBody>>::Future

Process the request and return the response asynchronously. Read more
source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> IntoRequest<T> for T

source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
source§

impl<M, S, Target, Request> MakeService<Target, Request> for M
where M: Service<Target, Response = S>, S: Service<Request>,

source§

type Response = <S as Service<Request>>::Response

Responses given by the service
source§

type Error = <S as Service<Request>>::Error

Errors produced by the service
source§

type Service = S

The Service value created by this factory
source§

type MakeError = <M as Service<Target>>::Error

Errors produced while building a service.
source§

type Future = <M as Service<Target>>::Future

The future of the Service instance.
source§

fn poll_ready( &mut self, cx: &mut Context<'_>, ) -> Poll<Result<(), <M as MakeService<Target, Request>>::MakeError>>

Returns Poll::Ready when the factory is able to create more services. Read more
source§

fn make_service( &mut self, target: Target, ) -> <M as MakeService<Target, Request>>::Future

Create and return a new service value asynchronously.
source§

fn into_service(self) -> IntoService<Self, Request>
where Self: Sized,

Consume this MakeService and convert it into a Service. Read more
source§

fn as_service(&mut self) -> AsService<'_, Self, Request>
where Self: Sized,

Convert this MakeService into a Service without consuming the original MakeService. Read more
source§

impl<M, S, Target, Request> MakeService<Target, Request> for M
where M: Service<Target, Response = S>, S: Service<Request>,

source§

type Response = <S as Service<Request>>::Response

Responses given by the service
source§

type Error = <S as Service<Request>>::Error

Errors produced by the service
source§

type Service = S

The Service value created by this factory
source§

type MakeError = <M as Service<Target>>::Error

Errors produced while building a service.
source§

type Future = <M as Service<Target>>::Future

The future of the Service instance.
source§

fn poll_ready( &mut self, cx: &mut Context<'_>, ) -> Poll<Result<(), <M as MakeService<Target, Request>>::MakeError>>

Returns Poll::Ready when the factory is able to create more services. Read more
source§

fn make_service( &mut self, target: Target, ) -> <M as MakeService<Target, Request>>::Future

Create and return a new service value asynchronously.
source§

fn into_service(self) -> IntoService<Self, Request>
where Self: Sized,

Consume this MakeService and convert it into a Service. Read more
source§

fn as_service(&mut self) -> AsService<'_, Self, Request>
where Self: Sized,

Convert this MakeService into a Service without consuming the original MakeService. Read more
source§

impl<S, R> ServiceExt<R> for S
where S: Service<R>,

source§

fn into_make_service(self) -> IntoMakeService<S>

Convert this service into a MakeService, that is a Service whose response is another service. Read more
source§

fn into_make_service_with_connect_info<C>( self, ) -> IntoMakeServiceWithConnectInfo<S, C>

Convert this service into a MakeService, that will store C’s associated ConnectInfo in a request extension such that ConnectInfo can extract it. Read more
source§

fn handle_error<F, T>(self, f: F) -> HandleError<Self, F, T>

Convert this service into a HandleError, that will handle errors by converting them into responses. Read more
source§

impl<T, Request> ServiceExt<Request> for T
where T: Service<Request> + ?Sized,

source§

fn ready(&mut self) -> Ready<'_, Self, Request>
where Self: Sized,

Yields a mutable reference to the service when it is ready to accept a request.
source§

fn ready_and(&mut self) -> Ready<'_, Self, Request>
where Self: Sized,

👎Deprecated since 0.4.6: please use the ServiceExt::ready method instead
Yields a mutable reference to the service when it is ready to accept a request.
source§

fn ready_oneshot(self) -> ReadyOneshot<Self, Request>
where Self: Sized,

Yields the service when it is ready to accept a request.
source§

fn oneshot(self, req: Request) -> Oneshot<Self, Request>
where Self: Sized,

Consume this Service, calling with the providing request once it is ready.
source§

fn call_all<S>(self, reqs: S) -> CallAll<Self, S>
where Self: Sized, Self::Error: Into<Box<dyn Error + Sync + Send>>, S: Stream<Item = Request>,

Process all requests from the given Stream, and produce a Stream of their responses. Read more
source§

fn and_then<F>(self, f: F) -> AndThen<Self, F>
where Self: Sized, F: Clone,

Executes a new future after this service’s future resolves. This does not alter the behaviour of the poll_ready method. Read more
source§

fn map_response<F, Response>(self, f: F) -> MapResponse<Self, F>
where Self: Sized, F: FnOnce(Self::Response) -> Response + Clone,

Maps this service’s response value to a different value. This does not alter the behaviour of the poll_ready method. Read more
source§

fn map_err<F, Error>(self, f: F) -> MapErr<Self, F>
where Self: Sized, F: FnOnce(Self::Error) -> Error + Clone,

Maps this service’s error value to a different value. This does not alter the behaviour of the poll_ready method. Read more
source§

fn map_result<F, Response, Error>(self, f: F) -> MapResult<Self, F>
where Self: Sized, Error: From<Self::Error>, F: FnOnce(Result<Self::Response, Self::Error>) -> Result<Response, Error> + Clone,

Maps this service’s result type (Result<Self::Response, Self::Error>) to a different value, regardless of whether the future succeeds or fails. Read more
source§

fn map_request<F, NewRequest>(self, f: F) -> MapRequest<Self, F>
where Self: Sized, F: FnMut(NewRequest) -> Request,

Composes a function in front of the service. Read more
source§

fn then<F, Response, Error, Fut>(self, f: F) -> Then<Self, F>
where Self: Sized, Error: From<Self::Error>, F: FnOnce(Result<Self::Response, Self::Error>) -> Fut + Clone, Fut: Future<Output = Result<Response, Error>>,

Composes an asynchronous function after this service. Read more
source§

fn map_future<F, Fut, Response, Error>(self, f: F) -> MapFuture<Self, F>
where Self: Sized, F: FnMut(Self::Future) -> Fut, Error: From<Self::Error>, Fut: Future<Output = Result<Response, Error>>,

Composes a function that transforms futures produced by the service. Read more
source§

fn boxed(self) -> BoxService<Request, Self::Response, Self::Error>
where Self: Sized + Send + 'static, Self::Future: Send + 'static,

Convert the service into a Service + Send trait object. Read more
source§

fn boxed_clone(self) -> BoxCloneService<Request, Self::Response, Self::Error>
where Self: Sized + Clone + Send + 'static, Self::Future: Send + 'static,

Convert the service into a Service + Clone + Send trait object. Read more
source§

impl<T, Request> ServiceExt<Request> for T
where T: Service<Request> + ?Sized,

source§

fn ready(&mut self) -> Ready<'_, Self, Request>
where Self: Sized,

Yields a mutable reference to the service when it is ready to accept a request.
source§

fn ready_oneshot(self) -> ReadyOneshot<Self, Request>
where Self: Sized,

Yields the service when it is ready to accept a request.
source§

fn oneshot(self, req: Request) -> Oneshot<Self, Request>
where Self: Sized,

Consume this Service, calling it with the provided request once it is ready.
source§

fn call_all<S>(self, reqs: S) -> CallAll<Self, S>
where Self: Sized, S: Stream<Item = Request>,

Process all requests from the given Stream, and produce a Stream of their responses. Read more
source§

fn and_then<F>(self, f: F) -> AndThen<Self, F>
where Self: Sized, F: Clone,

Executes a new future after this service’s future resolves. This does not alter the behaviour of the poll_ready method. Read more
source§

fn map_response<F, Response>(self, f: F) -> MapResponse<Self, F>
where Self: Sized, F: FnOnce(Self::Response) -> Response + Clone,

Maps this service’s response value to a different value. This does not alter the behaviour of the poll_ready method. Read more
source§

fn map_err<F, Error>(self, f: F) -> MapErr<Self, F>
where Self: Sized, F: FnOnce(Self::Error) -> Error + Clone,

Maps this service’s error value to a different value. This does not alter the behaviour of the poll_ready method. Read more
source§

fn map_result<F, Response, Error>(self, f: F) -> MapResult<Self, F>
where Self: Sized, Error: From<Self::Error>, F: FnOnce(Result<Self::Response, Self::Error>) -> Result<Response, Error> + Clone,

Maps this service’s result type (Result<Self::Response, Self::Error>) to a different value, regardless of whether the future succeeds or fails. Read more
source§

fn map_request<F, NewRequest>(self, f: F) -> MapRequest<Self, F>
where Self: Sized, F: FnMut(NewRequest) -> Request,

Composes a function in front of the service. Read more
source§

fn then<F, Response, Error, Fut>(self, f: F) -> Then<Self, F>
where Self: Sized, Error: From<Self::Error>, F: FnOnce(Result<Self::Response, Self::Error>) -> Fut + Clone, Fut: Future<Output = Result<Response, Error>>,

Composes an asynchronous function after this service. Read more
source§

fn map_future<F, Fut, Response, Error>(self, f: F) -> MapFuture<Self, F>
where Self: Sized, F: FnMut(Self::Future) -> Fut, Error: From<Self::Error>, Fut: Future<Output = Result<Response, Error>>,

Composes a function that transforms futures produced by the service. Read more
source§

fn boxed(self) -> BoxService<Request, Self::Response, Self::Error>
where Self: Sized + Send + 'static, Self::Future: Send + 'static,

Convert the service into a Service + Send trait object. Read more
source§

fn boxed_clone(self) -> BoxCloneService<Request, Self::Response, Self::Error>
where Self: Sized + Clone + Send + 'static, Self::Future: Send + 'static,

Convert the service into a Service + Clone + Send trait object. Read more
source§

impl<T> ToOwned for T
where T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

source§

fn vzip(self) -> V

source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more