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