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