axum/lib.rs
1//! axum is a web application framework 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 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`](crate::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`](crate::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//! You should prefer using [`State`] if possible since it's more type safe. The downside is that
187//! it's less dynamic than task-local variables and request extensions.
188//!
189//! See [`State`] for more details about accessing state.
190//!
191//! ## Using request extensions
192//!
193//! Another way to share state with handlers is using [`Extension`](crate::extract::Extension) as
194//! layer and extractor:
195//!
196//! ```rust,no_run
197//! use axum::{
198//! extract::Extension,
199//! routing::get,
200//! Router,
201//! };
202//! use std::sync::Arc;
203//!
204//! struct AppState {
205//! // ...
206//! }
207//!
208//! let shared_state = Arc::new(AppState { /* ... */ });
209//!
210//! let app = Router::new()
211//! .route("/", get(handler))
212//! .layer(Extension(shared_state));
213//!
214//! async fn handler(
215//! Extension(state): Extension<Arc<AppState>>,
216//! ) {
217//! // ...
218//! }
219//! # let _: Router = app;
220//! ```
221//!
222//! The downside to this approach is that you'll get runtime errors
223//! (specifically a `500 Internal Server Error` response) if you try and extract
224//! an extension that doesn't exist, perhaps because you forgot to add the
225//! middleware or because you're extracting the wrong type.
226//!
227//! ## Using closure captures
228//!
229//! State can also be passed directly to handlers using closure captures:
230//!
231//! ```rust,no_run
232//! use axum::{
233//! Json,
234//! extract::{Extension, Path},
235//! routing::{get, post},
236//! Router,
237//! };
238//! use std::sync::Arc;
239//! use serde::Deserialize;
240//!
241//! struct AppState {
242//! // ...
243//! }
244//!
245//! let shared_state = Arc::new(AppState { /* ... */ });
246//!
247//! let app = Router::new()
248//! .route(
249//! "/users",
250//! post({
251//! let shared_state = Arc::clone(&shared_state);
252//! move |body| create_user(body, shared_state)
253//! }),
254//! )
255//! .route(
256//! "/users/{id}",
257//! get({
258//! let shared_state = Arc::clone(&shared_state);
259//! move |path| get_user(path, shared_state)
260//! }),
261//! );
262//!
263//! async fn get_user(Path(user_id): Path<String>, state: Arc<AppState>) {
264//! // ...
265//! }
266//!
267//! async fn create_user(Json(payload): Json<CreateUserPayload>, state: Arc<AppState>) {
268//! // ...
269//! }
270//!
271//! #[derive(Deserialize)]
272//! struct CreateUserPayload {
273//! // ...
274//! }
275//! # let _: Router = app;
276//! ```
277//!
278//! The downside to this approach is that it's a the most verbose approach.
279//!
280//! ## Using task-local variables
281//!
282//! This also allows to share state with `IntoResponse` implementations:
283//!
284//! ```rust,no_run
285//! use axum::{
286//! extract::Request,
287//! http::{header, StatusCode},
288//! middleware::{self, Next},
289//! response::{IntoResponse, Response},
290//! routing::get,
291//! Router,
292//! };
293//! use tokio::task_local;
294//!
295//! #[derive(Clone)]
296//! struct CurrentUser {
297//! name: String,
298//! }
299//! task_local! {
300//! pub static USER: CurrentUser;
301//! }
302//!
303//! async fn auth(req: Request, next: Next) -> Result<Response, StatusCode> {
304//! let auth_header = req
305//! .headers()
306//! .get(header::AUTHORIZATION)
307//! .and_then(|header| header.to_str().ok())
308//! .ok_or(StatusCode::UNAUTHORIZED)?;
309//! if let Some(current_user) = authorize_current_user(auth_header).await {
310//! // State is setup here in the middleware
311//! Ok(USER.scope(current_user, next.run(req)).await)
312//! } else {
313//! Err(StatusCode::UNAUTHORIZED)
314//! }
315//! }
316//! async fn authorize_current_user(auth_token: &str) -> Option<CurrentUser> {
317//! Some(CurrentUser {
318//! name: auth_token.to_string(),
319//! })
320//! }
321//!
322//! struct UserResponse;
323//!
324//! impl IntoResponse for UserResponse {
325//! fn into_response(self) -> Response {
326//! // State is accessed here in the IntoResponse implementation
327//! let current_user = USER.with(|u| u.clone());
328//! (StatusCode::OK, current_user.name).into_response()
329//! }
330//! }
331//!
332//! async fn handler() -> UserResponse {
333//! UserResponse
334//! }
335//!
336//! let app: Router = Router::new()
337//! .route("/", get(handler))
338//! .route_layer(middleware::from_fn(auth));
339//! ```
340//!
341//! The main downside to this approach is that it only works when the async executor being used
342//! has the concept of task-local variables. The example above uses
343//! [tokio's `task_local` macro](https://docs.rs/tokio/1/tokio/macro.task_local.html).
344//! smol does not yet offer equivalent functionality at the time of writing (see
345//! [this GitHub issue](https://github.com/smol-rs/async-executor/issues/139)).
346//!
347//! # Building integrations for axum
348//!
349//! Libraries authors that want to provide [`FromRequest`], [`FromRequestParts`], or
350//! [`IntoResponse`] implementations should depend on the [`axum-core`] crate, instead of `axum` if
351//! possible. [`axum-core`] contains core types and traits and is less likely to receive breaking
352//! changes.
353//!
354//! # Required dependencies
355//!
356//! To use axum there are a few dependencies you have to pull in as well:
357//!
358//! ```toml
359//! [dependencies]
360//! axum = "<latest-version>"
361//! tokio = { version = "<latest-version>", features = ["full"] }
362//! tower = "<latest-version>"
363//! ```
364//!
365//! The `"full"` feature for tokio isn't necessary but it's the easiest way to get started.
366//!
367//! Tower isn't strictly necessary either but helpful for testing. See the
368//! testing example in the repo to learn more about testing axum apps.
369//!
370//! # Examples
371//!
372//! The axum repo contains [a number of examples][examples] that show how to put all the
373//! pieces together.
374//!
375//! # Feature flags
376//!
377//! axum uses a set of [feature flags] to reduce the amount of compiled and
378//! optional dependencies.
379//!
380//! The following optional features are available:
381//!
382//! Name | Description | Default?
383//! ---|---|---
384//! `http1` | Enables hyper's `http1` feature | Yes
385//! `http2` | Enables hyper's `http2` feature | No
386//! `json` | Enables the [`Json`] type and some similar convenience functionality | Yes
387//! `macros` | Enables optional utility macros | No
388//! `matched-path` | Enables capturing of every request's router path and the [`MatchedPath`] extractor | Yes
389//! `multipart` | Enables parsing `multipart/form-data` requests with [`Multipart`] | No
390//! `original-uri` | Enables capturing of every request's original URI and the [`OriginalUri`] extractor | Yes
391//! `tokio` | Enables `tokio` as a dependency and `axum::serve`, `SSE` and `extract::connect_info` types. | Yes
392//! `tower-log` | Enables `tower`'s `log` feature | Yes
393//! `tracing` | Log rejections from built-in extractors | Yes
394//! `ws` | Enables WebSockets support via [`extract::ws`] | No
395//! `form` | Enables the `Form` extractor | Yes
396//! `query` | Enables the `Query` extractor | Yes
397//!
398//! [`MatchedPath`]: crate::extract::MatchedPath
399//! [`Multipart`]: crate::extract::Multipart
400//! [`OriginalUri`]: crate::extract::OriginalUri
401//! [`tower`]: https://crates.io/crates/tower
402//! [`tower-http`]: https://crates.io/crates/tower-http
403//! [`tokio`]: http://crates.io/crates/tokio
404//! [`hyper`]: http://crates.io/crates/hyper
405//! [`tonic`]: http://crates.io/crates/tonic
406//! [feature flags]: https://doc.rust-lang.org/cargo/reference/features.html#the-features-section
407//! [`IntoResponse`]: crate::response::IntoResponse
408//! [`Timeout`]: tower::timeout::Timeout
409//! [examples]: https://github.com/tokio-rs/axum/tree/main/examples
410//! [`Router::merge`]: crate::routing::Router::merge
411//! [`Service`]: tower::Service
412//! [`Service::poll_ready`]: tower::Service::poll_ready
413//! [`Service`'s]: tower::Service
414//! [`tower::Service`]: tower::Service
415//! [tower-guides]: https://github.com/tower-rs/tower/tree/master/guides
416//! [`Uuid`]: https://docs.rs/uuid/latest/uuid/
417//! [`FromRequest`]: crate::extract::FromRequest
418//! [`FromRequestParts`]: crate::extract::FromRequestParts
419//! [`HeaderMap`]: http::header::HeaderMap
420//! [`Request`]: http::Request
421//! [customize-extractor-error]: https://github.com/tokio-rs/axum/blob/main/examples/customize-extractor-error/src/main.rs
422//! [axum-macros]: https://docs.rs/axum-macros
423//! [`debug_handler`]: https://docs.rs/axum-macros/latest/axum_macros/attr.debug_handler.html
424//! [`Handler`]: crate::handler::Handler
425//! [`Infallible`]: std::convert::Infallible
426//! [load shed]: tower::load_shed
427//! [`axum-core`]: http://crates.io/crates/axum-core
428//! [`State`]: crate::extract::State
429
430#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
431#![cfg_attr(test, allow(clippy::float_cmp))]
432#![cfg_attr(not(test), warn(clippy::print_stdout, clippy::dbg_macro))]
433
434#[macro_use]
435pub(crate) mod macros;
436
437mod boxed;
438mod extension;
439#[cfg(feature = "form")]
440mod form;
441#[cfg(feature = "json")]
442mod json;
443mod service_ext;
444mod util;
445
446pub mod body;
447pub mod error_handling;
448pub mod extract;
449pub mod handler;
450pub mod middleware;
451pub mod response;
452pub mod routing;
453#[cfg(all(feature = "tokio", any(feature = "http1", feature = "http2")))]
454pub mod serve;
455
456#[cfg(any(test, feature = "__private"))]
457#[allow(missing_docs, missing_debug_implementations, clippy::print_stdout)]
458pub mod test_helpers;
459
460#[doc(no_inline)]
461pub use http;
462
463#[doc(inline)]
464pub use self::extension::Extension;
465#[doc(inline)]
466#[cfg(feature = "json")]
467pub use self::json::Json;
468#[doc(inline)]
469pub use self::routing::Router;
470
471#[doc(inline)]
472#[cfg(feature = "form")]
473pub use self::form::Form;
474
475#[doc(inline)]
476pub use axum_core::{BoxError, Error, RequestExt, RequestPartsExt};
477
478#[cfg(feature = "macros")]
479pub use axum_macros::{debug_handler, debug_middleware};
480
481#[cfg(all(feature = "tokio", any(feature = "http1", feature = "http2")))]
482#[doc(inline)]
483pub use self::serve::serve;
484
485pub use self::service_ext::ServiceExt;
486
487#[cfg(test)]
488use axum_macros::__private_axum_test as test;