axum/
lib.rs

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