Struct axum::routing::method_routing::MethodRouter
source · pub struct MethodRouter<S = (), E = Infallible> { /* private fields */ }
Expand description
A Service
that accepts requests based on a MethodFilter
and
allows chaining additional handlers and services.
§When does MethodRouter
implement Service
?
Whether or not MethodRouter
implements Service
depends on the state type it requires.
use tower::Service;
use axum::{routing::get, extract::{State, Request}, body::Body};
// this `MethodRouter` doesn't require any state, i.e. the state is `()`,
let method_router = get(|| async {});
// and thus it implements `Service`
assert_service(method_router);
// this requires a `String` and doesn't implement `Service`
let method_router = get(|_: State<String>| async {});
// until you provide the `String` with `.with_state(...)`
let method_router_with_state = method_router.with_state(String::new());
// and then it implements `Service`
assert_service(method_router_with_state);
// helper to check that a value implements `Service`
fn assert_service<S>(service: S)
where
S: Service<Request>,
{}
Implementations§
source§impl<S> MethodRouter<S, Infallible>where
S: Clone,
impl<S> MethodRouter<S, Infallible>where
S: Clone,
sourcepub fn on<H, T>(self, filter: MethodFilter, handler: H) -> Self
pub fn on<H, T>(self, filter: MethodFilter, handler: H) -> Self
Chain an additional handler that will accept requests matching the given
MethodFilter
.
§Example
use axum::{
routing::get,
Router,
routing::MethodFilter
};
async fn handler() {}
async fn other_handler() {}
// Requests to `GET /` will go to `handler` and `DELETE /` will go to
// `other_handler`
let app = Router::new().route("/", get(handler).on(MethodFilter::DELETE, other_handler));
sourcepub fn delete<H, T>(self, handler: H) -> Self
pub fn delete<H, T>(self, handler: H) -> Self
Chain an additional handler that will only accept DELETE
requests.
See MethodRouter::get
for an example.
sourcepub fn get<H, T>(self, handler: H) -> Self
pub fn get<H, T>(self, handler: H) -> Self
Chain an additional handler that will only accept GET
requests.
§Example
use axum::{routing::post, Router};
async fn handler() {}
async fn other_handler() {}
// Requests to `POST /` will go to `handler` and `GET /` will go to
// `other_handler`.
let app = Router::new().route("/", post(handler).get(other_handler));
Note that get
routes will also be called for HEAD
requests but will have
the response body removed. Make sure to add explicit HEAD
routes
afterwards.
sourcepub fn head<H, T>(self, handler: H) -> Self
pub fn head<H, T>(self, handler: H) -> Self
Chain an additional handler that will only accept HEAD
requests.
See MethodRouter::get
for an example.
sourcepub fn options<H, T>(self, handler: H) -> Self
pub fn options<H, T>(self, handler: H) -> Self
Chain an additional handler that will only accept OPTIONS
requests.
See MethodRouter::get
for an example.
sourcepub fn patch<H, T>(self, handler: H) -> Self
pub fn patch<H, T>(self, handler: H) -> Self
Chain an additional handler that will only accept PATCH
requests.
See MethodRouter::get
for an example.
sourcepub fn post<H, T>(self, handler: H) -> Self
pub fn post<H, T>(self, handler: H) -> Self
Chain an additional handler that will only accept POST
requests.
See MethodRouter::get
for an example.
sourcepub fn put<H, T>(self, handler: H) -> Self
pub fn put<H, T>(self, handler: H) -> Self
Chain an additional handler that will only accept PUT
requests.
See MethodRouter::get
for an example.
sourcepub fn trace<H, T>(self, handler: H) -> Self
pub fn trace<H, T>(self, handler: H) -> Self
Chain an additional handler that will only accept TRACE
requests.
See MethodRouter::get
for an example.
source§impl MethodRouter<(), Infallible>
impl MethodRouter<(), Infallible>
sourcepub fn into_make_service(self) -> IntoMakeService<Self>
pub fn into_make_service(self) -> IntoMakeService<Self>
Convert the router into a MakeService
.
This allows you to serve a single MethodRouter
if you don’t need any
routing based on the path:
use axum::{
handler::Handler,
http::{Uri, Method},
response::IntoResponse,
routing::get,
};
use std::net::SocketAddr;
async fn handler(method: Method, uri: Uri, body: String) -> String {
format!("received `{method} {uri}` with body `{body:?}`")
}
let router = get(handler).post(handler);
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, router.into_make_service()).await.unwrap();
sourcepub fn into_make_service_with_connect_info<C>(
self,
) -> IntoMakeServiceWithConnectInfo<Self, C>
pub fn into_make_service_with_connect_info<C>( self, ) -> IntoMakeServiceWithConnectInfo<Self, C>
Convert the router into a MakeService
which stores information
about the incoming connection.
See Router::into_make_service_with_connect_info
for more details.
use axum::{
handler::Handler,
response::IntoResponse,
extract::ConnectInfo,
routing::get,
};
use std::net::SocketAddr;
async fn handler(ConnectInfo(addr): ConnectInfo<SocketAddr>) -> String {
format!("Hello {addr}")
}
let router = get(handler).post(handler);
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, router.into_make_service()).await.unwrap();
source§impl<S, E> MethodRouter<S, E>where
S: Clone,
impl<S, E> MethodRouter<S, E>where
S: Clone,
sourcepub fn new() -> Self
pub fn new() -> Self
Create a default MethodRouter
that will respond with 405 Method Not Allowed
to all
requests.
sourcepub fn with_state<S2>(self, state: S) -> MethodRouter<S2, E>
pub fn with_state<S2>(self, state: S) -> MethodRouter<S2, E>
Provide the state for the router.
sourcepub fn on_service<T>(self, filter: MethodFilter, svc: T) -> Self
pub fn on_service<T>(self, filter: MethodFilter, svc: T) -> Self
Chain an additional service that will accept requests matching the given
MethodFilter
.
§Example
use axum::{
extract::Request,
Router,
routing::{MethodFilter, on_service},
body::Body,
};
use http::Response;
use std::convert::Infallible;
let service = tower::service_fn(|request: Request| async {
Ok::<_, Infallible>(Response::new(Body::empty()))
});
// Requests to `DELETE /` will go to `service`
let app = Router::new().route("/", on_service(MethodFilter::DELETE, service));
sourcepub fn delete_service<T>(self, svc: T) -> Self
pub fn delete_service<T>(self, svc: T) -> Self
Chain an additional service that will only accept DELETE
requests.
See MethodRouter::get_service
for an example.
sourcepub fn get_service<T>(self, svc: T) -> Self
pub fn get_service<T>(self, svc: T) -> Self
Chain an additional service that will only accept GET
requests.
§Example
use axum::{
extract::Request,
Router,
routing::post_service,
body::Body,
};
use http::Response;
use std::convert::Infallible;
let service = tower::service_fn(|request: Request| async {
Ok::<_, Infallible>(Response::new(Body::empty()))
});
let other_service = tower::service_fn(|request: Request| async {
Ok::<_, Infallible>(Response::new(Body::empty()))
});
// Requests to `POST /` will go to `service` and `GET /` will go to
// `other_service`.
let app = Router::new().route("/", post_service(service).get_service(other_service));
Note that get
routes will also be called for HEAD
requests but will have
the response body removed. Make sure to add explicit HEAD
routes
afterwards.
sourcepub fn head_service<T>(self, svc: T) -> Self
pub fn head_service<T>(self, svc: T) -> Self
Chain an additional service that will only accept HEAD
requests.
See MethodRouter::get_service
for an example.
sourcepub fn options_service<T>(self, svc: T) -> Self
pub fn options_service<T>(self, svc: T) -> Self
Chain an additional service that will only accept OPTIONS
requests.
See MethodRouter::get_service
for an example.
sourcepub fn patch_service<T>(self, svc: T) -> Self
pub fn patch_service<T>(self, svc: T) -> Self
Chain an additional service that will only accept PATCH
requests.
See MethodRouter::get_service
for an example.
sourcepub fn post_service<T>(self, svc: T) -> Self
pub fn post_service<T>(self, svc: T) -> Self
Chain an additional service that will only accept POST
requests.
See MethodRouter::get_service
for an example.
sourcepub fn put_service<T>(self, svc: T) -> Self
pub fn put_service<T>(self, svc: T) -> Self
Chain an additional service that will only accept PUT
requests.
See MethodRouter::get_service
for an example.
sourcepub fn trace_service<T>(self, svc: T) -> Self
pub fn trace_service<T>(self, svc: T) -> Self
Chain an additional service that will only accept TRACE
requests.
See MethodRouter::get_service
for an example.
sourcepub fn fallback_service<T>(self, svc: T) -> Self
pub fn fallback_service<T>(self, svc: T) -> Self
Add a fallback service 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, Method, Uri},
};
let handler = get(|| async {}).fallback(fallback);
let app = Router::new().route("/", handler);
async fn fallback(method: Method, uri: Uri) -> (StatusCode, String) {
(StatusCode::NOT_FOUND, format!("`{method}` not allowed for {uri}"))
}
§When used with MethodRouter::merge
Two routers that both have a fallback cannot be merged. Doing so results in a panic:
use axum::{
routing::{get, post},
handler::Handler,
response::IntoResponse,
http::{StatusCode, Uri},
};
let one = get(|| async {}).fallback(fallback_one);
let two = post(|| async {}).fallback(fallback_two);
let method_route = one.merge(two);
async fn fallback_one() -> impl IntoResponse { /* ... */ }
async fn fallback_two() -> impl IntoResponse { /* ... */ }
§Setting the Allow
header
By default MethodRouter
will set the Allow
header when returning 405 Method Not Allowed
. This is also done when the fallback is used unless the response
generated by the fallback already sets the Allow
header.
This means if you use fallback
to accept additional methods, you should make
sure you set the Allow
header correctly.
sourcepub fn layer<L, NewError>(self, layer: L) -> MethodRouter<S, NewError>where
L: Layer<Route<E>> + Clone + Send + 'static,
L::Service: Service<Request> + Clone + Send + 'static,
<L::Service as Service<Request>>::Response: IntoResponse + 'static,
<L::Service as Service<Request>>::Error: Into<NewError> + 'static,
<L::Service as Service<Request>>::Future: Send + 'static,
E: 'static,
S: 'static,
NewError: 'static,
pub fn layer<L, NewError>(self, layer: L) -> MethodRouter<S, NewError>where
L: Layer<Route<E>> + Clone + Send + 'static,
L::Service: Service<Request> + Clone + Send + 'static,
<L::Service as Service<Request>>::Response: IntoResponse + 'static,
<L::Service as Service<Request>>::Error: Into<NewError> + 'static,
<L::Service as Service<Request>>::Future: Send + 'static,
E: 'static,
S: 'static,
NewError: '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.
Works similarly to Router::layer
. See that method for
more details.
§Example
use axum::{routing::get, Router};
use tower::limit::ConcurrencyLimitLayer;
async fn handler() {}
let app = Router::new().route(
"/",
// All requests to `GET /` will be sent through `ConcurrencyLimitLayer`
get(handler).layer(ConcurrencyLimitLayer::new(64)),
);
sourcepub fn route_layer<L>(self, layer: L) -> MethodRouter<S, E>
pub fn route_layer<L>(self, layer: L) -> MethodRouter<S, E>
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 MethodRouter::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 405 Method Not Allowed
into a
401 Unauthorized
.
§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`
// `POST /FOO` with a invalid token will receive `405 Method Not Allowed`
sourcepub fn merge(self, other: MethodRouter<S, E>) -> Self
pub fn merge(self, other: MethodRouter<S, E>) -> Self
Merge two routers into one.
This is useful for breaking routers into smaller pieces and combining them into one.
use axum::{
routing::{get, post},
Router,
};
let get = get(|| async {});
let post = post(|| async {});
let merged = get.merge(post);
let app = Router::new().route("/", merged);
// Our app now accepts
// - GET /
// - POST /
sourcepub fn handle_error<F, T>(self, f: F) -> MethodRouter<S, Infallible>where
F: Clone + Send + Sync + 'static,
HandleError<Route<E>, F, T>: Service<Request, Error = Infallible>,
<HandleError<Route<E>, F, T> as Service<Request>>::Future: Send,
<HandleError<Route<E>, F, T> as Service<Request>>::Response: IntoResponse + Send,
T: 'static,
E: 'static,
S: 'static,
pub fn handle_error<F, T>(self, f: F) -> MethodRouter<S, Infallible>where
F: Clone + Send + Sync + 'static,
HandleError<Route<E>, F, T>: Service<Request, Error = Infallible>,
<HandleError<Route<E>, F, T> as Service<Request>>::Future: Send,
<HandleError<Route<E>, F, T> as Service<Request>>::Response: IntoResponse + Send,
T: 'static,
E: 'static,
S: 'static,
Apply a HandleErrorLayer
.
This is a convenience method for doing self.layer(HandleErrorLayer::new(f))
.
Trait Implementations§
source§impl<S, E> Clone for MethodRouter<S, E>
impl<S, E> Clone for MethodRouter<S, E>
source§impl<S, E> Debug for MethodRouter<S, E>
impl<S, E> Debug for MethodRouter<S, E>
source§impl<S, E> Default for MethodRouter<S, E>where
S: Clone,
impl<S, E> Default for MethodRouter<S, E>where
S: Clone,
source§impl<S> Handler<(), S> for MethodRouter<S>where
S: Clone + 'static,
impl<S> Handler<(), S> for MethodRouter<S>where
S: Clone + 'static,
source§type Future = InfallibleRouteFuture
type Future = InfallibleRouteFuture
source§fn call(self, req: Request, state: S) -> Self::Future
fn call(self, req: Request, state: S) -> Self::Future
source§fn layer<L>(self, layer: L) -> Layered<L, Self, T, S>
fn layer<L>(self, layer: L) -> Layered<L, Self, T, S>
tower::Layer
to the handler. Read moresource§fn with_state(self, state: S) -> HandlerService<Self, T, S>
fn with_state(self, state: S) -> HandlerService<Self, T, S>
Service
by providing the statesource§impl Service<IncomingStream<'_>> for MethodRouter<()>
impl Service<IncomingStream<'_>> for MethodRouter<()>
source§type Response = MethodRouter
type Response = MethodRouter
source§type Error = Infallible
type Error = Infallible
source§type Future = Ready<Result<<MethodRouter as Service<IncomingStream<'_>>>::Response, <MethodRouter as Service<IncomingStream<'_>>>::Error>>
type Future = Ready<Result<<MethodRouter as Service<IncomingStream<'_>>>::Response, <MethodRouter as Service<IncomingStream<'_>>>::Error>>
Auto Trait Implementations§
impl<S = (), E = Infallible> !Freeze for MethodRouter<S, E>
impl<S, E> RefUnwindSafe for MethodRouter<S, E>
impl<S, E> Send for MethodRouter<S, E>
impl<S, E> Sync for MethodRouter<S, E>
impl<S, E> Unpin for MethodRouter<S, E>
impl<S, E> UnwindSafe for MethodRouter<S, E>
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)source§impl<H, T> HandlerWithoutStateExt<T> for H
impl<H, T> HandlerWithoutStateExt<T> for H
source§fn into_service(self) -> HandlerService<H, T, ()>
fn into_service(self) -> HandlerService<H, T, ()>
Service
and no state.source§fn into_make_service(self) -> IntoMakeService<HandlerService<H, T, ()>>
fn into_make_service(self) -> IntoMakeService<HandlerService<H, T, ()>>
MakeService
and no state. Read moresource§fn into_make_service_with_connect_info<C>(
self,
) -> IntoMakeServiceWithConnectInfo<HandlerService<H, T, ()>, C>
fn into_make_service_with_connect_info<C>( self, ) -> IntoMakeServiceWithConnectInfo<HandlerService<H, T, ()>, C>
MakeService
which stores information
about the incoming connection and has no state. Read moresource§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
source§impl<M, S, Target, Request> MakeService<Target, Request> for M
impl<M, S, Target, Request> MakeService<Target, Request> for M
source§fn poll_ready(
&mut self,
cx: &mut Context<'_>,
) -> Poll<Result<(), <M as MakeService<Target, Request>>::MakeError>>
fn poll_ready( &mut self, cx: &mut Context<'_>, ) -> Poll<Result<(), <M as MakeService<Target, Request>>::MakeError>>
Poll::Ready
when the factory is able to create more services. Read moresource§fn make_service(
&mut self,
target: Target,
) -> <M as MakeService<Target, Request>>::Future
fn make_service( &mut self, target: Target, ) -> <M as MakeService<Target, Request>>::Future
source§fn into_service(self) -> IntoService<Self, Request>where
Self: Sized,
fn into_service(self) -> IntoService<Self, Request>where
Self: Sized,
source§fn as_service(&mut self) -> AsService<'_, Self, Request>where
Self: Sized,
fn as_service(&mut self) -> AsService<'_, Self, Request>where
Self: Sized,
source§impl<S, R> ServiceExt<R> for Swhere
S: Service<R>,
impl<S, R> ServiceExt<R> for Swhere
S: Service<R>,
source§fn into_make_service(self) -> IntoMakeService<S>
fn into_make_service(self) -> IntoMakeService<S>
MakeService
, that is a Service
whose
response is another service. Read moresource§fn into_make_service_with_connect_info<C>(
self,
) -> IntoMakeServiceWithConnectInfo<S, C>
fn into_make_service_with_connect_info<C>( self, ) -> IntoMakeServiceWithConnectInfo<S, C>
MakeService
, that will store C
’s
associated ConnectInfo
in a request extension such that ConnectInfo
can extract it. Read moresource§fn handle_error<F, T>(self, f: F) -> HandleError<Self, F, T>
fn handle_error<F, T>(self, f: F) -> HandleError<Self, F, T>
HandleError
, that will handle errors
by converting them into responses. Read moresource§impl<T, Request> ServiceExt<Request> for T
impl<T, Request> ServiceExt<Request> for T
source§fn ready(&mut self) -> Ready<'_, Self, Request>where
Self: Sized,
fn ready(&mut self) -> Ready<'_, Self, Request>where
Self: Sized,
source§fn ready_oneshot(self) -> ReadyOneshot<Self, Request>where
Self: Sized,
fn ready_oneshot(self) -> ReadyOneshot<Self, Request>where
Self: Sized,
source§fn oneshot(self, req: Request) -> Oneshot<Self, Request>where
Self: Sized,
fn oneshot(self, req: Request) -> Oneshot<Self, Request>where
Self: Sized,
Service
, calling it with the provided request once it is ready.source§fn and_then<F>(self, f: F) -> AndThen<Self, F>
fn and_then<F>(self, f: F) -> AndThen<Self, F>
poll_ready
method. Read moresource§fn map_response<F, Response>(self, f: F) -> MapResponse<Self, F>
fn map_response<F, Response>(self, f: F) -> MapResponse<Self, F>
poll_ready
method. Read moresource§fn map_err<F, Error>(self, f: F) -> MapErr<Self, F>
fn map_err<F, Error>(self, f: F) -> MapErr<Self, F>
poll_ready
method. Read moresource§fn map_result<F, Response, Error>(self, f: F) -> MapResult<Self, F>
fn map_result<F, Response, Error>(self, f: F) -> MapResult<Self, F>
Result<Self::Response, Self::Error>
)
to a different value, regardless of whether the future succeeds or
fails. Read more