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