Skip to main content

axum/
lib.rs

1//! axum is an HTTP routing and request-handling library that focuses on ergonomics and modularity.
2//!
3//! # High-level features
4//!
5//! - Route requests to handlers with a macro-free API.
6//! - Declaratively parse requests using extractors.
7//! - Simple and predictable error handling model.
8//! - Generate responses with minimal boilerplate.
9//! - Take full advantage of the [`tower`] and [`tower-http`] ecosystem of
10//!   middleware, services, and utilities.
11//!
12//! In particular, the last point is what sets `axum` apart from other libraries / frameworks.
13//! `axum` doesn't have its own middleware system but instead uses
14//! [`tower::Service`]. This means `axum` gets timeouts, tracing, compression,
15//! authorization, and more, for free. It also enables you to share middleware with
16//! applications written using [`hyper`] or [`tonic`].
17//!
18//! # Compatibility
19//!
20//! axum is designed to work with [tokio] and [hyper]. Runtime and
21//! transport layer independence is not a goal, at least for the time being.
22//!
23//! # Example
24//!
25//! The "Hello, World!" of axum is:
26//!
27//! ```rust,no_run
28//! use axum::{
29//!     routing::get,
30//!     Router,
31//! };
32//!
33//! #[tokio::main]
34//! async fn main() {
35//!     // build our application with a single route
36//!     let app = Router::new().route("/", get(|| async { "Hello, World!" }));
37//!
38//!     // run our app with hyper, listening globally on port 3000
39//!     let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
40//!     axum::serve(listener, app).await.unwrap();
41//! }
42//! ```
43//!
44//! Note using `#[tokio::main]` requires you enable tokio's `macros` and `rt-multi-thread` features
45//! or just `full` to enable all features (`cargo add tokio --features macros,rt-multi-thread`).
46//!
47//! # Routing
48//!
49//! [`Router`] is used to set up which paths go to which services:
50//!
51//! ```rust
52//! use axum::{Router, routing::get};
53//!
54//! // our router
55//! let app = Router::new()
56//!     .route("/", get(root))
57//!     .route("/foo", get(get_foo).post(post_foo))
58//!     .route("/foo/bar", get(foo_bar));
59//!
60//! // which calls one of these handlers
61//! async fn root() {}
62//! async fn get_foo() {}
63//! async fn post_foo() {}
64//! async fn foo_bar() {}
65//! # let _: Router = app;
66//! ```
67//!
68//! See [`Router`] for more details on routing.
69//!
70//! # Handlers
71//!
72#![doc = include_str!("docs/handlers_intro.md")]
73//!
74//! See [`handler`](crate::handler) for more details on handlers.
75//!
76//! # Extractors
77//!
78//! An extractor is a type that implements [`FromRequest`] or [`FromRequestParts`]. Extractors are
79//! how you pick apart the incoming request to get the parts your handler needs.
80//!
81//! ```rust
82//! use axum::extract::{Path, Query, Json};
83//! use std::collections::HashMap;
84//!
85//! // `Path` gives you the path parameters and deserializes them.
86//! async fn path(Path(user_id): Path<u32>) {}
87//!
88//! // `Query` gives you the query parameters and deserializes them.
89//! async fn query(Query(params): Query<HashMap<String, String>>) {}
90//!
91//! // Buffer the request body and deserialize it as JSON into a
92//! // `serde_json::Value`. `Json` supports any type that implements
93//! // `serde::Deserialize`.
94//! async fn json(Json(payload): Json<serde_json::Value>) {}
95//! ```
96//!
97//! See [`extract`](crate::extract) for more details on extractors.
98//!
99//! # Responses
100//!
101//! Anything that implements [`IntoResponse`] can be returned from handlers.
102//!
103//! ```rust,no_run
104//! use axum::{
105//!     body::Body,
106//!     routing::get,
107//!     response::Json,
108//!     Router,
109//! };
110//! use serde_json::{Value, json};
111//!
112//! // `&'static str` becomes a `200 OK` with `content-type: text/plain; charset=utf-8`
113//! async fn plain_text() -> &'static str {
114//!     "foo"
115//! }
116//!
117//! // `Json` gives a content-type of `application/json` and works with any type
118//! // that implements `serde::Serialize`
119//! async fn json() -> Json<Value> {
120//!     Json(json!({ "data": 42 }))
121//! }
122//!
123//! let app = Router::new()
124//!     .route("/plain_text", get(plain_text))
125//!     .route("/json", get(json));
126//! # let _: Router = app;
127//! ```
128//!
129//! See [`response`](crate::response) for more details on building responses.
130//!
131//! # Error handling
132//!
133//! axum aims to have a simple and predictable error handling model. That means
134//! it is simple to convert errors into responses and you are guaranteed that
135//! all errors are handled.
136//!
137//! See [`error_handling`] for more details on axum's
138//! error handling model and how to handle errors gracefully.
139//!
140//! # Middleware
141//!
142//! There are several different ways to write middleware for axum. See
143//! [`middleware`] for more details.
144//!
145//! # Sharing state with handlers
146//!
147//! It is common to share some state between handlers. For example, a
148//! pool of database connections or clients to other services may need to
149//! be shared.
150//!
151//! The four most common ways of doing that are:
152//!
153//! - Using the [`State`] extractor
154//! - Using request extensions
155//! - Using closure captures
156//! - Using task-local variables
157//!
158//! ## Using the [`State`] extractor
159//!
160//! ```rust,no_run
161//! use axum::{
162//!     extract::State,
163//!     routing::get,
164//!     Router,
165//! };
166//! use std::sync::Arc;
167//!
168//! struct AppState {
169//!     // ...
170//! }
171//!
172//! let shared_state = Arc::new(AppState { /* ... */ });
173//!
174//! let app = Router::new()
175//!     .route("/", get(handler))
176//!     .with_state(shared_state);
177//!
178//! async fn handler(
179//!     State(state): State<Arc<AppState>>,
180//! ) {
181//!     // ...
182//! }
183//! # let _: Router = app;
184//! ```
185//!
186//! State is cloned for every request. Wrapping your state in `Arc` makes those
187//! clones cheap. If all fields are already cheap to clone (for example, each field
188//! is itself an `Arc` or a copy type), you can `#[derive(Clone)]` directly on the
189//! struct instead.
190//!
191//! ### Substates with `FromRef`
192//!
193//! When a handler only needs part of the application state, use [`FromRef`] to extract
194//! a substate. Implement the trait manually, or derive it with `#[derive(FromRef)]`
195//! (requires the `macros` feature):
196//!
197//! ```rust
198//! use axum::{Router, routing::get, extract::{State, FromRef}};
199//!
200//! #[derive(Clone)]
201//! struct AppState {
202//!     api_state: ApiState,
203//! }
204//!
205//! #[derive(Clone)]
206//! struct ApiState {}
207//!
208//! // Teach axum how to produce an `ApiState` from a reference to `AppState`.
209//! impl FromRef<AppState> for ApiState {
210//!     fn from_ref(app_state: &AppState) -> ApiState {
211//!         app_state.api_state.clone()
212//!     }
213//! }
214//!
215//! let app = Router::new()
216//!     .route("/", get(handler))
217//!     .with_state(AppState { api_state: ApiState {} });
218//!
219//! // This handler receives only the `ApiState` slice; it never sees `AppState`.
220//! async fn handler(State(api_state): State<ApiState>) {}
221//! # let _: Router = app;
222//! ```
223//!
224//! ### The `Router<S>` type parameter
225//!
226//! `Router<S>` when `S` is not `()` means a router that is _missing_ a state of type `S`. Calling
227//! [`.with_state(s)`][Router::with_state] provides that state and typically produces a
228//! `Router<()>`, which is the only form that can be passed to [`serve()`]. See
229//! [`Router::with_state`] for a full explanation.
230//!
231//! You should prefer using [`State`] if possible since it's more type safe. The downside is that
232//! it's less dynamic than task-local variables and request extensions.
233//!
234//! See [`State`] for more details about accessing state.
235//!
236//! ## Using request extensions
237//!
238//! Another way to share state with handlers is using [`Extension`] as
239//! layer and extractor:
240//!
241//! ```rust,no_run
242//! use axum::{
243//!     extract::Extension,
244//!     routing::get,
245//!     Router,
246//! };
247//! use std::sync::Arc;
248//!
249//! struct AppState {
250//!     // ...
251//! }
252//!
253//! let shared_state = Arc::new(AppState { /* ... */ });
254//!
255//! let app = Router::new()
256//!     .route("/", get(handler))
257//!     .layer(Extension(shared_state));
258//!
259//! async fn handler(
260//!     Extension(state): Extension<Arc<AppState>>,
261//! ) {
262//!     // ...
263//! }
264//! # let _: Router = app;
265//! ```
266//!
267//! The downside to this approach is that you'll get runtime errors
268//! (specifically a `500 Internal Server Error` response) if you try and extract
269//! an extension that doesn't exist, perhaps because you forgot to add the
270//! middleware or because you're extracting the wrong type.
271//!
272//! ## Using closure captures
273//!
274//! State can also be passed directly to handlers using closure captures:
275//!
276//! ```rust,no_run
277//! use axum::{
278//!     Json,
279//!     extract::{Extension, Path},
280//!     routing::{get, post},
281//!     Router,
282//! };
283//! use std::sync::Arc;
284//! use serde::Deserialize;
285//!
286//! struct AppState {
287//!     // ...
288//! }
289//!
290//! let shared_state = Arc::new(AppState { /* ... */ });
291//!
292//! let app = Router::new()
293//!     .route(
294//!         "/users",
295//!         post({
296//!             let shared_state = Arc::clone(&shared_state);
297//!             move |body| create_user(body, shared_state)
298//!         }),
299//!     )
300//!     .route(
301//!         "/users/{id}",
302//!         get({
303//!             let shared_state = Arc::clone(&shared_state);
304//!             move |path| get_user(path, shared_state)
305//!         }),
306//!     );
307//!
308//! async fn get_user(Path(user_id): Path<String>, state: Arc<AppState>) {
309//!     // ...
310//! }
311//!
312//! async fn create_user(Json(payload): Json<CreateUserPayload>, state: Arc<AppState>) {
313//!     // ...
314//! }
315//!
316//! #[derive(Deserialize)]
317//! struct CreateUserPayload {
318//!     // ...
319//! }
320//! # let _: Router = app;
321//! ```
322//!
323//! The downside to this approach is that it's the most verbose approach.
324//!
325//! ## Using task-local variables
326//!
327//! This also allows to share state with `IntoResponse` implementations:
328//!
329//! ```rust,no_run
330//! use axum::{
331//!     extract::Request,
332//!     http::{header, StatusCode},
333//!     middleware::{self, Next},
334//!     response::{IntoResponse, Response},
335//!     routing::get,
336//!     Router,
337//! };
338//! use tokio::task_local;
339//!
340//! #[derive(Clone)]
341//! struct CurrentUser {
342//!     name: String,
343//! }
344//! task_local! {
345//!     pub static USER: CurrentUser;
346//! }
347//!
348//! async fn auth(req: Request, next: Next) -> Result<Response, StatusCode> {
349//!     let auth_header = req
350//!         .headers()
351//!         .get(header::AUTHORIZATION)
352//!         .and_then(|header| header.to_str().ok())
353//!         .ok_or(StatusCode::UNAUTHORIZED)?;
354//!     if let Some(current_user) = authorize_current_user(auth_header).await {
355//!         // State is setup here in the middleware
356//!         Ok(USER.scope(current_user, next.run(req)).await)
357//!     } else {
358//!         Err(StatusCode::UNAUTHORIZED)
359//!     }
360//! }
361//! async fn authorize_current_user(auth_token: &str) -> Option<CurrentUser> {
362//!     Some(CurrentUser {
363//!         name: auth_token.to_string(),
364//!     })
365//! }
366//!
367//! struct UserResponse;
368//!
369//! impl IntoResponse for UserResponse {
370//!     fn into_response(self) -> Response {
371//!         // State is accessed here in the IntoResponse implementation
372//!         let current_user = USER.with(|u| u.clone());
373//!         (StatusCode::OK, current_user.name).into_response()
374//!     }
375//! }
376//!
377//! async fn handler() -> UserResponse {
378//!     UserResponse
379//! }
380//!
381//! let app: Router = Router::new()
382//!     .route("/", get(handler))
383//!     .route_layer(middleware::from_fn(auth));
384//! ```
385//!
386//! The main downside to this approach is that it only works when the async executor being used
387//! has the concept of task-local variables. The example above uses
388//! [tokio's `task_local` macro](https://docs.rs/tokio/1/tokio/macro.task_local.html).
389//! smol does not yet offer equivalent functionality at the time of writing (see
390//! [this GitHub issue](https://github.com/smol-rs/async-executor/issues/139)).
391//!
392//! # Building integrations for axum
393//!
394//! Libraries authors that want to provide [`FromRequest`], [`FromRequestParts`], or
395//! [`IntoResponse`] implementations should depend on the [`axum-core`] crate, instead of `axum` if
396//! possible. [`axum-core`] contains core types and traits and is less likely to receive breaking
397//! changes.
398//!
399//! # Required dependencies
400//!
401//! To use axum there are a few dependencies you have to pull in as well:
402//!
403//! ```toml
404//! [dependencies]
405//! axum = "<latest-version>"
406//! tokio = { version = "<latest-version>", features = ["full"] }
407//! tower = "<latest-version>"
408//! ```
409//!
410//! The `"full"` feature for tokio isn't necessary but it's the easiest way to get started.
411//!
412//! Tower isn't strictly necessary either but helpful for testing. See the
413//! testing example in the repo to learn more about testing axum apps.
414//!
415//! # Examples
416//!
417//! The axum repo contains [a number of examples][examples] that show how to put all the
418//! pieces together.
419//!
420//! # Feature flags
421//!
422//! axum uses a set of [feature flags] to reduce the amount of compiled and
423//! optional dependencies.
424//!
425//! The following optional features are available:
426//!
427//! Name | Description | Default?
428//! ---|---|---
429//! `http1` | Enables hyper's `http1` feature | <span role="img" aria-label="Default feature">✔</span>
430//! `http2` | Enables hyper's `http2` feature |
431//! `json` | Enables the [`Json`] type and some similar convenience functionality | <span role="img" aria-label="Default feature">✔</span>
432//! `macros` | Enables optional utility macros |
433//! `matched-path` | Enables capturing of every request's router path and the [`MatchedPath`] extractor | <span role="img" aria-label="Default feature">✔</span>
434//! `multipart` | Enables parsing `multipart/form-data` requests with [`Multipart`] |
435//! `original-uri` | Enables capturing of every request's original URI and the [`OriginalUri`] extractor | <span role="img" aria-label="Default feature">✔</span>
436//! `tokio` | Enables `tokio` as a dependency and `axum::serve`, `SSE` and `extract::connect_info` types. | <span role="img" aria-label="Default feature">✔</span>
437//! `tower-log` | Enables `tower`'s `log` feature | <span role="img" aria-label="Default feature">✔</span>
438//! `tracing` | Log rejections from built-in extractors | <span role="img" aria-label="Default feature">✔</span>
439//! `ws` | Enables WebSockets support via [`extract::ws`] |
440//! `form` | Enables the `Form` extractor | <span role="img" aria-label="Default feature">✔</span>
441//! `query` | Enables the `Query` extractor | <span role="img" aria-label="Default feature">✔</span>
442//!
443//! [`MatchedPath`]: crate::extract::MatchedPath
444//! [`Multipart`]: crate::extract::Multipart
445//! [`OriginalUri`]: crate::extract::OriginalUri
446//! [`tower`]: https://crates.io/crates/tower
447//! [`tower-http`]: https://crates.io/crates/tower-http
448//! [`tokio`]: http://crates.io/crates/tokio
449//! [`hyper`]: http://crates.io/crates/hyper
450//! [`tonic`]: http://crates.io/crates/tonic
451//! [feature flags]: https://doc.rust-lang.org/cargo/reference/features.html#the-features-section
452//! [`IntoResponse`]: crate::response::IntoResponse
453//! [`Timeout`]: tower::timeout::Timeout
454//! [examples]: https://github.com/tokio-rs/axum/tree/main/examples
455//! [`Router::merge`]: crate::routing::Router::merge
456//! [`Service`]: tower::Service
457//! [`Service::poll_ready`]: tower::Service::poll_ready
458//! [`Service`'s]: tower::Service
459//! [`tower::Service`]: tower::Service
460//! [tower-guides]: https://github.com/tower-rs/tower/tree/master/guides
461//! [`Uuid`]: https://docs.rs/uuid/latest/uuid/
462//! [`FromRequest`]: crate::extract::FromRequest
463//! [`FromRequestParts`]: crate::extract::FromRequestParts
464//! [`HeaderMap`]: http::header::HeaderMap
465//! [`Request`]: http::Request
466//! [customize-extractor-error]: https://github.com/tokio-rs/axum/blob/main/examples/customize-extractor-error/src/main.rs
467//! [axum-macros]: https://docs.rs/axum-macros
468//! [`debug_handler`]: https://docs.rs/axum-macros/latest/axum_macros/attr.debug_handler.html
469//! [`Handler`]: crate::handler::Handler
470//! [`Infallible`]: std::convert::Infallible
471//! [load shed]: tower::load_shed
472//! [`axum-core`]: http://crates.io/crates/axum-core
473//! [`State`]: crate::extract::State
474//! [`FromRef`]: crate::extract::FromRef
475//! [`Router::with_state`]: crate::routing::Router::with_state
476
477#![cfg_attr(docsrs, feature(doc_cfg))]
478#![cfg_attr(test, allow(clippy::float_cmp))]
479#![cfg_attr(not(test), warn(clippy::print_stdout, clippy::dbg_macro))]
480
481#[macro_use]
482pub(crate) mod macros;
483
484mod boxed;
485mod extension;
486#[cfg(feature = "form")]
487mod form;
488#[cfg(feature = "json")]
489mod json;
490mod service_ext;
491mod util;
492
493pub mod body;
494pub mod error_handling;
495pub mod extract;
496pub mod handler;
497pub mod middleware;
498pub mod response;
499pub mod routing;
500#[cfg(all(feature = "tokio", any(feature = "http1", feature = "http2")))]
501pub mod serve;
502
503#[cfg(any(test, feature = "__private"))]
504#[allow(missing_docs, missing_debug_implementations, clippy::print_stdout)]
505pub mod test_helpers;
506
507#[doc(no_inline)]
508pub use http;
509
510#[doc(inline)]
511pub use self::extension::Extension;
512#[doc(inline)]
513#[cfg(feature = "json")]
514pub use self::json::Json;
515#[doc(inline)]
516pub use self::routing::Router;
517
518#[doc(inline)]
519#[cfg(feature = "form")]
520pub use self::form::Form;
521
522#[doc(inline)]
523pub use axum_core::{BoxError, Error, RequestExt, RequestPartsExt};
524
525#[cfg(feature = "macros")]
526pub use axum_macros::{debug_handler, debug_middleware};
527
528#[cfg(all(feature = "tokio", any(feature = "http1", feature = "http2")))]
529#[doc(inline)]
530pub use self::serve::serve;
531
532pub use self::service_ext::ServiceExt;
533
534#[cfg(test)]
535use axum_macros::__private_axum_test as test;