axum/handler/mod.rs
1//! Async functions that can be used to handle requests.
2//!
3#![doc = include_str!("../docs/handlers_intro.md")]
4//!
5//! Some examples of handlers:
6//!
7//! ```rust
8//! use axum::{body::Bytes, http::StatusCode};
9//!
10//! // Handler that immediately returns an empty `200 OK` response.
11//! async fn unit_handler() {}
12//!
13//! // Handler that immediately returns a `200 OK` response with a plain text
14//! // body.
15//! async fn string_handler() -> String {
16//! "Hello, World!".to_string()
17//! }
18//!
19//! // Handler that buffers the request body and returns it.
20//! //
21//! // This works because `Bytes` implements `FromRequest`
22//! // and therefore can be used as an extractor.
23//! //
24//! // `String` and `StatusCode` both implement `IntoResponse` and
25//! // therefore `Result<String, StatusCode>` also implements `IntoResponse`
26//! async fn echo(body: Bytes) -> Result<String, StatusCode> {
27//! if let Ok(string) = String::from_utf8(body.to_vec()) {
28//! Ok(string)
29//! } else {
30//! Err(StatusCode::BAD_REQUEST)
31//! }
32//! }
33//! ```
34//!
35//! Instead of a direct `StatusCode`, it makes sense to use intermediate error type
36//! that can ultimately be converted to `Response`. This allows using `?` operator
37//! in handlers. See those examples:
38//!
39//! * [`anyhow-error-response`][anyhow] for generic boxed errors
40//! * [`error-handling`][error-handling] for application-specific detailed errors
41//!
42//! [anyhow]: https://github.com/tokio-rs/axum/blob/main/examples/anyhow-error-response/src/main.rs
43//! [error-handling]: https://github.com/tokio-rs/axum/blob/main/examples/error-handling/src/main.rs
44//!
45#![doc = include_str!("../docs/debugging_handler_type_errors.md")]
46
47#[cfg(feature = "tokio")]
48use crate::extract::connect_info::IntoMakeServiceWithConnectInfo;
49use crate::{
50 extract::{FromRequest, FromRequestParts, Request},
51 response::{IntoResponse, Response},
52 routing::IntoMakeService,
53};
54use std::{convert::Infallible, fmt, future::Future, marker::PhantomData, pin::Pin};
55use tower::ServiceExt;
56use tower_layer::Layer;
57use tower_service::Service;
58
59pub mod future;
60mod service;
61
62pub use self::service::HandlerService;
63
64/// Trait for async functions that can be used to handle requests.
65///
66/// You shouldn't need to depend on this trait directly. It is automatically
67/// implemented to closures of the right types.
68///
69/// See the [module docs](crate::handler) for more details.
70///
71/// # Converting `Handler`s into [`Service`]s
72///
73/// To convert `Handler`s into [`Service`]s you have to call either
74/// [`HandlerWithoutStateExt::into_service`] or [`Handler::with_state`]:
75///
76/// ```
77/// use tower::Service;
78/// use axum::{
79/// extract::{State, Request},
80/// body::Body,
81/// handler::{HandlerWithoutStateExt, Handler},
82/// };
83///
84/// // this handler doesn't require any state
85/// async fn one() {}
86/// // so it can be converted to a service with `HandlerWithoutStateExt::into_service`
87/// assert_service(one.into_service());
88///
89/// // this handler requires state
90/// async fn two(_: State<String>) {}
91/// // so we have to provide it
92/// let handler_with_state = two.with_state(String::new());
93/// // which gives us a `Service`
94/// assert_service(handler_with_state);
95///
96/// // helper to check that a value implements `Service`
97/// fn assert_service<S>(service: S)
98/// where
99/// S: Service<Request>,
100/// {}
101/// ```
102#[doc = include_str!("../docs/debugging_handler_type_errors.md")]
103///
104/// # Handlers that aren't functions
105///
106/// The `Handler` trait is also implemented for `T: IntoResponse`. That allows easily returning
107/// fixed data for routes:
108///
109/// ```
110/// use axum::{
111/// Router,
112/// routing::{get, post},
113/// Json,
114/// http::StatusCode,
115/// };
116/// use serde_json::json;
117///
118/// let app = Router::new()
119/// // respond with a fixed string
120/// .route("/", get("Hello, World!"))
121/// // or return some mock data
122/// .route("/users", post((
123/// StatusCode::CREATED,
124/// Json(json!({ "id": 1, "username": "alice" })),
125/// )));
126/// # let _: Router = app;
127/// ```
128///
129/// # About type parameter `T`
130///
131/// **Generally you shouldn't need to worry about `T`**; when calling methods such as
132/// [`post`](crate::routing::method_routing::post) it will be automatically inferred and this is
133/// the intended way for this parameter to be provided in application code.
134///
135/// If you are implementing your own methods that accept implementations of `Handler` as
136/// arguments, then the following may be useful:
137///
138/// The type parameter `T` is a workaround for trait coherence rules, allowing us to
139/// write blanket implementations of `Handler` over many types of handler functions
140/// with different numbers of arguments, without the compiler forbidding us from doing
141/// so because one type `F` can in theory implement both `Fn(A) -> X` and `Fn(A, B) -> Y`.
142/// `T` is a placeholder taking on a representation of the parameters of the handler function,
143/// as well as other similar 'coherence rule workaround' discriminators,
144/// allowing us to select one function signature to use as a `Handler`.
145#[diagnostic::on_unimplemented(
146 note = "Consider using `#[axum::debug_handler]` to improve the error message"
147)]
148pub trait Handler<T, S>: Clone + Send + Sync + Sized + 'static {
149 /// The type of future calling this handler returns.
150 type Future: Future<Output = Response> + Send + 'static;
151
152 /// Call the handler with the given request.
153 fn call(self, req: Request, state: S) -> Self::Future;
154
155 /// Apply a [`tower::Layer`] to the handler.
156 ///
157 /// All requests to the handler will be processed by the layer's
158 /// corresponding middleware.
159 ///
160 /// This can be used to add additional processing to a request for a single
161 /// handler.
162 ///
163 /// Note this differs from [`routing::Router::layer`](crate::routing::Router::layer)
164 /// which adds a middleware to a group of routes.
165 ///
166 /// If you're applying middleware that produces errors you have to handle the errors
167 /// so they're converted into responses. You can learn more about doing that
168 /// [here](crate::error_handling).
169 ///
170 /// # Example
171 ///
172 /// Adding the [`tower::limit::ConcurrencyLimit`] middleware to a handler
173 /// can be done like so:
174 ///
175 /// ```rust
176 /// use axum::{
177 /// routing::get,
178 /// handler::Handler,
179 /// Router,
180 /// };
181 /// use tower::limit::{ConcurrencyLimitLayer, ConcurrencyLimit};
182 ///
183 /// async fn handler() { /* ... */ }
184 ///
185 /// let layered_handler = handler.layer(ConcurrencyLimitLayer::new(64));
186 /// let app = Router::new().route("/", get(layered_handler));
187 /// # let _: Router = app;
188 /// ```
189 fn layer<L>(self, layer: L) -> Layered<L, Self, T, S>
190 where
191 L: Layer<HandlerService<Self, T, S>> + Clone,
192 L::Service: Service<Request>,
193 {
194 Layered {
195 layer,
196 handler: self,
197 _marker: PhantomData,
198 }
199 }
200
201 /// Convert the handler into a [`Service`] by providing the state
202 fn with_state(self, state: S) -> HandlerService<Self, T, S> {
203 HandlerService::new(self, state)
204 }
205}
206
207#[diagnostic::do_not_recommend]
208impl<F, Fut, Res, S> Handler<((),), S> for F
209where
210 F: FnOnce() -> Fut + Clone + Send + Sync + 'static,
211 Fut: Future<Output = Res> + Send,
212 Res: IntoResponse,
213{
214 type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
215
216 fn call(self, _req: Request, _state: S) -> Self::Future {
217 Box::pin(async move { self().await.into_response() })
218 }
219}
220
221macro_rules! impl_handler {
222 (
223 [$($ty:ident),*], $last:ident
224 ) => {
225 #[diagnostic::do_not_recommend]
226 #[allow(non_snake_case, unused_mut)]
227 impl<F, Fut, S, Res, M, $($ty,)* $last> Handler<(M, $($ty,)* $last,), S> for F
228 where
229 F: FnOnce($($ty,)* $last,) -> Fut + Clone + Send + Sync + 'static,
230 Fut: Future<Output = Res> + Send,
231 S: Send + Sync + 'static,
232 Res: IntoResponse,
233 $( $ty: FromRequestParts<S> + Send, )*
234 $last: FromRequest<S, M> + Send,
235 {
236 type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
237
238 fn call(self, req: Request, state: S) -> Self::Future {
239 let (mut parts, body) = req.into_parts();
240 Box::pin(async move {
241 $(
242 let $ty = match $ty::from_request_parts(&mut parts, &state).await {
243 Ok(value) => value,
244 Err(rejection) => return rejection.into_response(),
245 };
246 )*
247
248 let req = Request::from_parts(parts, body);
249
250 let $last = match $last::from_request(req, &state).await {
251 Ok(value) => value,
252 Err(rejection) => return rejection.into_response(),
253 };
254
255 self($($ty,)* $last,).await.into_response()
256 })
257 }
258 }
259 };
260}
261
262all_the_tuples!(impl_handler);
263
264mod private {
265 // Marker type for `impl<T: IntoResponse> Handler for T`
266 #[allow(missing_debug_implementations)]
267 pub enum IntoResponseHandler {}
268}
269
270#[diagnostic::do_not_recommend]
271impl<T, S> Handler<private::IntoResponseHandler, S> for T
272where
273 T: IntoResponse + Clone + Send + Sync + 'static,
274{
275 type Future = std::future::Ready<Response>;
276
277 fn call(self, _req: Request, _state: S) -> Self::Future {
278 std::future::ready(self.into_response())
279 }
280}
281
282/// A [`Service`] created from a [`Handler`] by applying a Tower middleware.
283///
284/// Created with [`Handler::layer`]. See that method for more details.
285pub struct Layered<L, H, T, S> {
286 layer: L,
287 handler: H,
288 _marker: PhantomData<fn() -> (T, S)>,
289}
290
291impl<L, H, T, S> fmt::Debug for Layered<L, H, T, S>
292where
293 L: fmt::Debug,
294{
295 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
296 f.debug_struct("Layered")
297 .field("layer", &self.layer)
298 .finish()
299 }
300}
301
302impl<L, H, T, S> Clone for Layered<L, H, T, S>
303where
304 L: Clone,
305 H: Clone,
306{
307 fn clone(&self) -> Self {
308 Self {
309 layer: self.layer.clone(),
310 handler: self.handler.clone(),
311 _marker: PhantomData,
312 }
313 }
314}
315
316#[diagnostic::do_not_recommend]
317impl<H, S, T, L> Handler<T, S> for Layered<L, H, T, S>
318where
319 L: Layer<HandlerService<H, T, S>> + Clone + Send + Sync + 'static,
320 H: Handler<T, S>,
321 L::Service: Service<Request, Error = Infallible> + Clone + Send + 'static,
322 <L::Service as Service<Request>>::Response: IntoResponse,
323 <L::Service as Service<Request>>::Future: Send,
324 T: 'static,
325 S: 'static,
326{
327 type Future = future::LayeredFuture<L::Service>;
328
329 fn call(self, req: Request, state: S) -> Self::Future {
330 use futures_util::future::{FutureExt, Map};
331
332 let svc = self.handler.with_state(state);
333 let svc = self.layer.layer(svc);
334
335 let future: Map<
336 _,
337 fn(
338 Result<
339 <L::Service as Service<Request>>::Response,
340 <L::Service as Service<Request>>::Error,
341 >,
342 ) -> _,
343 > = svc.oneshot(req).map(|result| match result {
344 Ok(res) => res.into_response(),
345 Err(err) => match err {},
346 });
347
348 future::LayeredFuture::new(future)
349 }
350}
351
352/// Extension trait for [`Handler`]s that don't have state.
353///
354/// This provides convenience methods to convert the [`Handler`] into a [`Service`] or [`MakeService`].
355///
356/// [`MakeService`]: tower::make::MakeService
357pub trait HandlerWithoutStateExt<T>: Handler<T, ()> {
358 /// Convert the handler into a [`Service`] and no state.
359 fn into_service(self) -> HandlerService<Self, T, ()>;
360
361 /// Convert the handler into a [`MakeService`] and no state.
362 ///
363 /// See [`HandlerService::into_make_service`] for more details.
364 ///
365 /// [`MakeService`]: tower::make::MakeService
366 fn into_make_service(self) -> IntoMakeService<HandlerService<Self, T, ()>>;
367
368 /// Convert the handler into a [`MakeService`] which stores information
369 /// about the incoming connection and has no state.
370 ///
371 /// See [`HandlerService::into_make_service_with_connect_info`] for more details.
372 ///
373 /// [`MakeService`]: tower::make::MakeService
374 #[cfg(feature = "tokio")]
375 fn into_make_service_with_connect_info<C>(
376 self,
377 ) -> IntoMakeServiceWithConnectInfo<HandlerService<Self, T, ()>, C>;
378}
379
380impl<H, T> HandlerWithoutStateExt<T> for H
381where
382 H: Handler<T, ()>,
383{
384 fn into_service(self) -> HandlerService<Self, T, ()> {
385 self.with_state(())
386 }
387
388 fn into_make_service(self) -> IntoMakeService<HandlerService<Self, T, ()>> {
389 self.into_service().into_make_service()
390 }
391
392 #[cfg(feature = "tokio")]
393 fn into_make_service_with_connect_info<C>(
394 self,
395 ) -> IntoMakeServiceWithConnectInfo<HandlerService<Self, T, ()>, C> {
396 self.into_service().into_make_service_with_connect_info()
397 }
398}
399
400#[cfg(test)]
401mod tests {
402 use super::*;
403 use crate::{extract::State, test_helpers::*};
404 use axum_core::body::Body;
405 use http::StatusCode;
406 use std::time::Duration;
407 use tower_http::{
408 limit::RequestBodyLimitLayer, map_request_body::MapRequestBodyLayer,
409 map_response_body::MapResponseBodyLayer, timeout::TimeoutLayer,
410 };
411
412 #[crate::test]
413 async fn handler_into_service() {
414 async fn handle(body: String) -> impl IntoResponse {
415 format!("you said: {body}")
416 }
417
418 let client = TestClient::new(handle.into_service());
419
420 let res = client.post("/").body("hi there!").await;
421 assert_eq!(res.status(), StatusCode::OK);
422 assert_eq!(res.text().await, "you said: hi there!");
423 }
424
425 #[crate::test]
426 async fn with_layer_that_changes_request_body_and_state() {
427 async fn handle(State(state): State<&'static str>) -> &'static str {
428 state
429 }
430
431 let svc = handle
432 .layer((
433 RequestBodyLimitLayer::new(1024),
434 TimeoutLayer::with_status_code(
435 StatusCode::REQUEST_TIMEOUT,
436 Duration::from_secs(10),
437 ),
438 MapResponseBodyLayer::new(Body::new),
439 ))
440 .layer(MapRequestBodyLayer::new(Body::new))
441 .with_state("foo");
442
443 let client = TestClient::new(svc);
444 let res = client.get("/").await;
445 assert_eq!(res.text().await, "foo");
446 }
447}