mirror of
https://github.com/tokio-rs/axum.git
synced 2026-09-06 00:00:17 +02:00
Type safe state inheritance (#1532)
* Make state type safe * fix examples * remove unnecessary `#[track_caller]`s * Router::into_service -> Router::with_state * fixup docs * macro docs * add missing docs * fix examples * format * changelog * Update trybuild tests * Make sure fallbacks are still inherited for opaque services (#1540) * Document nesting routers with different state * fix leftover conflicts
This commit is contained in:
@@ -25,7 +25,7 @@ syn = { version = "1.0", features = [
|
||||
] }
|
||||
|
||||
[dev-dependencies]
|
||||
axum = { path = "../axum", version = "0.6.0-rc.2", features = ["headers"] }
|
||||
axum = { path = "../axum", version = "0.6.0-rc.2", features = ["headers", "macros"] }
|
||||
axum-extra = { path = "../axum-extra", version = "0.4.0-rc.1", features = ["typed-routing", "cookie-private"] }
|
||||
rustversion = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
||||
+13
-13
@@ -181,7 +181,6 @@ use from_request::Trait::{FromRequest, FromRequestParts};
|
||||
/// rejection type with `#[from_request(rejection(YourType))]`:
|
||||
///
|
||||
/// ```
|
||||
/// use axum_macros::FromRequest;
|
||||
/// use axum::{
|
||||
/// extract::{
|
||||
/// rejection::{ExtensionRejection, StringRejection},
|
||||
@@ -463,8 +462,7 @@ pub fn derive_from_request_parts(item: TokenStream) -> TokenStream {
|
||||
/// As the error message says, handler function needs to be async.
|
||||
///
|
||||
/// ```
|
||||
/// use axum::{routing::get, Router};
|
||||
/// use axum_macros::debug_handler;
|
||||
/// use axum::{routing::get, Router, debug_handler};
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() {
|
||||
@@ -493,8 +491,7 @@ pub fn derive_from_request_parts(item: TokenStream) -> TokenStream {
|
||||
/// To work around that the request body type can be customized like so:
|
||||
///
|
||||
/// ```
|
||||
/// use axum::{body::BoxBody, http::Request};
|
||||
/// # use axum_macros::debug_handler;
|
||||
/// use axum::{body::BoxBody, http::Request, debug_handler};
|
||||
///
|
||||
/// #[debug_handler(body = BoxBody)]
|
||||
/// async fn handler(request: Request<BoxBody>) {}
|
||||
@@ -506,8 +503,7 @@ pub fn derive_from_request_parts(item: TokenStream) -> TokenStream {
|
||||
/// [`axum::extract::State`] argument:
|
||||
///
|
||||
/// ```
|
||||
/// use axum::extract::State;
|
||||
/// # use axum_macros::debug_handler;
|
||||
/// use axum::{debug_handler, extract::State};
|
||||
///
|
||||
/// #[debug_handler]
|
||||
/// async fn handler(
|
||||
@@ -523,8 +519,7 @@ pub fn derive_from_request_parts(item: TokenStream) -> TokenStream {
|
||||
/// customize the state type you can set it with `#[debug_handler(state = ...)]`:
|
||||
///
|
||||
/// ```
|
||||
/// use axum::extract::{State, FromRef};
|
||||
/// # use axum_macros::debug_handler;
|
||||
/// use axum::{debug_handler, extract::{State, FromRef}};
|
||||
///
|
||||
/// #[debug_handler(state = AppState)]
|
||||
/// async fn handler(
|
||||
@@ -579,8 +574,11 @@ pub fn derive_typed_path(input: TokenStream) -> TokenStream {
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use axum_macros::FromRef;
|
||||
/// use axum::{Router, routing::get, extract::State};
|
||||
/// use axum::{
|
||||
/// Router,
|
||||
/// routing::get,
|
||||
/// extract::{State, FromRef},
|
||||
/// };
|
||||
///
|
||||
/// #
|
||||
/// # type AuthToken = String;
|
||||
@@ -605,8 +603,10 @@ pub fn derive_typed_path(input: TokenStream) -> TokenStream {
|
||||
/// database_pool,
|
||||
/// };
|
||||
///
|
||||
/// let app = Router::with_state(state).route("/", get(handler).post(other_handler));
|
||||
/// # let _: Router<AppState> = app;
|
||||
/// let app = Router::new()
|
||||
/// .route("/", get(handler).post(other_handler))
|
||||
/// .with_state(state);
|
||||
/// # let _: axum::routing::RouterService = app;
|
||||
/// ```
|
||||
///
|
||||
/// [`FromRef`]: https://docs.rs/axum/latest/axum/extract/trait.FromRef.html
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use axum_macros::FromRef;
|
||||
use axum::{Router, routing::get, extract::State};
|
||||
use axum::{Router, routing::get, extract::{State, FromRef}};
|
||||
|
||||
// This will implement `FromRef` for each field in the struct.
|
||||
#[derive(Clone, FromRef)]
|
||||
@@ -15,5 +14,7 @@ fn main() {
|
||||
auth_token: Default::default(),
|
||||
};
|
||||
|
||||
let _: Router<AppState> = Router::with_state(state).route("/", get(handler));
|
||||
let _: axum::routing::RouterService = Router::new()
|
||||
.route("/", get(handler))
|
||||
.with_state(state);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use axum::{extract::FromRequestParts, response::Response};
|
||||
use axum_macros::FromRequestParts;
|
||||
|
||||
#[derive(FromRequestParts)]
|
||||
struct Extractor {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
error[E0277]: the trait bound `String: FromRequestParts<S>` is not satisfied
|
||||
--> tests/from_request/fail/parts_extracting_body.rs:6:11
|
||||
--> tests/from_request/fail/parts_extracting_body.rs:5:11
|
||||
|
|
||||
6 | body: String,
|
||||
5 | body: String,
|
||||
| ^^^^^^ the trait `FromRequestParts<S>` is not implemented for `String`
|
||||
|
|
||||
= help: the following other types implement trait `FromRequestParts<S>`:
|
||||
|
||||
@@ -3,7 +3,6 @@ use axum::{
|
||||
extract::{FromRequest, Json},
|
||||
response::Response,
|
||||
};
|
||||
use axum_macros::FromRequest;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize, FromRequest)]
|
||||
|
||||
@@ -2,7 +2,6 @@ use axum::{
|
||||
extract::{FromRequestParts, Extension},
|
||||
response::Response,
|
||||
};
|
||||
use axum_macros::FromRequestParts;
|
||||
|
||||
#[derive(Clone, FromRequestParts)]
|
||||
#[from_request(via(Extension))]
|
||||
|
||||
@@ -4,7 +4,6 @@ use axum::{
|
||||
response::Response,
|
||||
headers::{self, UserAgent},
|
||||
};
|
||||
use axum_macros::FromRequest;
|
||||
|
||||
#[derive(FromRequest)]
|
||||
struct Extractor {
|
||||
|
||||
@@ -3,7 +3,6 @@ use axum::{
|
||||
headers::{self, UserAgent},
|
||||
response::Response,
|
||||
};
|
||||
use axum_macros::FromRequestParts;
|
||||
|
||||
#[derive(FromRequestParts)]
|
||||
struct Extractor {
|
||||
|
||||
@@ -7,7 +7,6 @@ use axum::{
|
||||
},
|
||||
headers::{self, UserAgent},
|
||||
};
|
||||
use axum_macros::FromRequest;
|
||||
|
||||
#[derive(FromRequest)]
|
||||
struct Extractor {
|
||||
|
||||
@@ -6,7 +6,6 @@ use axum::{
|
||||
},
|
||||
headers::{self, UserAgent},
|
||||
};
|
||||
use axum_macros::FromRequestParts;
|
||||
|
||||
#[derive(FromRequestParts)]
|
||||
struct Extractor {
|
||||
|
||||
@@ -6,7 +6,6 @@ use axum::{
|
||||
routing::get,
|
||||
Extension, Router,
|
||||
};
|
||||
use axum_macros::FromRequest;
|
||||
|
||||
fn main() {
|
||||
let _: Router = Router::new().route("/", get(handler).post(handler_result));
|
||||
|
||||
@@ -6,7 +6,6 @@ use axum::{
|
||||
routing::get,
|
||||
Extension, Router,
|
||||
};
|
||||
use axum_macros::FromRequestParts;
|
||||
|
||||
fn main() {
|
||||
let _: Router = Router::new().route("/", get(handler).post(handler_result));
|
||||
|
||||
@@ -6,9 +6,10 @@ use axum::{
|
||||
use axum_macros::FromRequest;
|
||||
|
||||
fn main() {
|
||||
let _: Router<AppState> = Router::with_state(AppState::default())
|
||||
let _: axum::routing::RouterService = Router::new()
|
||||
.route("/a", get(|_: AppState| async {}))
|
||||
.route("/b", get(|_: InnerState| async {}));
|
||||
.route("/b", get(|_: InnerState| async {}))
|
||||
.with_state(AppState::default());
|
||||
}
|
||||
|
||||
#[derive(Clone, FromRequest)]
|
||||
|
||||
@@ -6,10 +6,11 @@ use axum::{
|
||||
use axum_macros::FromRequestParts;
|
||||
|
||||
fn main() {
|
||||
let _: Router<AppState> = Router::with_state(AppState::default())
|
||||
let _: axum::routing::RouterService = Router::new()
|
||||
.route("/a", get(|_: AppState| async {}))
|
||||
.route("/b", get(|_: InnerState| async {}))
|
||||
.route("/c", get(|_: AppState, _: InnerState| async {}));
|
||||
.route("/c", get(|_: AppState, _: InnerState| async {}))
|
||||
.with_state(AppState::default());
|
||||
}
|
||||
|
||||
#[derive(Clone, FromRequestParts)]
|
||||
|
||||
@@ -6,8 +6,9 @@ use axum::{
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let _: Router<AppState> = Router::with_state(AppState::default())
|
||||
.route("/b", get(|_: Extractor| async {}));
|
||||
let _: axum::routing::RouterService = Router::new()
|
||||
.route("/b", get(|_: Extractor| async {}))
|
||||
.with_state(AppState::default());
|
||||
}
|
||||
|
||||
#[derive(FromRequest)]
|
||||
|
||||
@@ -7,8 +7,9 @@ use axum::{
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn main() {
|
||||
let _: Router<AppState> = Router::with_state(AppState::default())
|
||||
.route("/b", get(|_: Extractor| async {}));
|
||||
let _: axum::routing::RouterService = Router::new()
|
||||
.route("/b", get(|_: Extractor| async {}))
|
||||
.with_state(AppState::default());
|
||||
}
|
||||
|
||||
#[derive(FromRequestParts)]
|
||||
|
||||
@@ -6,8 +6,9 @@ use axum::{
|
||||
use axum_macros::FromRequest;
|
||||
|
||||
fn main() {
|
||||
let _: Router<AppState> = Router::with_state(AppState::default())
|
||||
.route("/", get(|_: Extractor| async {}));
|
||||
let _: axum::routing::RouterService = Router::new()
|
||||
.route("/", get(|_: Extractor| async {}))
|
||||
.with_state(AppState::default());
|
||||
}
|
||||
|
||||
#[derive(FromRequest)]
|
||||
|
||||
@@ -6,8 +6,9 @@ use axum::{
|
||||
use axum_macros::FromRequest;
|
||||
|
||||
fn main() {
|
||||
let _: Router<AppState> = Router::with_state(AppState::default())
|
||||
.route("/", get(|_: Extractor| async {}));
|
||||
let _: axum::routing::RouterService = Router::new()
|
||||
.route("/", get(|_: Extractor| async {}))
|
||||
.with_state(AppState::default());
|
||||
}
|
||||
|
||||
#[derive(FromRequest)]
|
||||
|
||||
@@ -6,9 +6,10 @@ use axum::{
|
||||
use axum_macros::FromRequest;
|
||||
|
||||
fn main() {
|
||||
let _: Router<AppState> = Router::with_state(AppState::default())
|
||||
let _: axum::routing::RouterService = Router::new()
|
||||
.route("/b", get(|_: (), _: AppState| async {}))
|
||||
.route("/c", get(|_: (), _: InnerState| async {}));
|
||||
.route("/c", get(|_: (), _: InnerState| async {}))
|
||||
.with_state(AppState::default());
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, FromRequest)]
|
||||
|
||||
@@ -6,8 +6,9 @@ use axum::{
|
||||
use axum_macros::FromRequest;
|
||||
|
||||
fn main() {
|
||||
let _: Router<AppState> = Router::with_state(AppState::default())
|
||||
.route("/b", get(|_: AppState| async {}));
|
||||
let _: axum::routing::RouterService = Router::new()
|
||||
.route("/b", get(|_: AppState| async {}))
|
||||
.with_state(AppState::default());
|
||||
}
|
||||
|
||||
// if we're extract "via" `State<AppState>` and not specifying state
|
||||
|
||||
@@ -6,10 +6,11 @@ use axum::{
|
||||
use axum_macros::FromRequestParts;
|
||||
|
||||
fn main() {
|
||||
let _: Router<AppState> = Router::with_state(AppState::default())
|
||||
let _: axum::routing::RouterService = Router::new()
|
||||
.route("/a", get(|_: AppState, _: InnerState, _: String| async {}))
|
||||
.route("/b", get(|_: AppState, _: String| async {}))
|
||||
.route("/c", get(|_: InnerState, _: String| async {}));
|
||||
.route("/c", get(|_: InnerState, _: String| async {}))
|
||||
.with_state(AppState::default());
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, FromRequestParts)]
|
||||
|
||||
@@ -8,8 +8,9 @@ use axum::{
|
||||
use axum_macros::FromRequest;
|
||||
|
||||
fn main() {
|
||||
let _: Router<AppState> =
|
||||
Router::with_state(AppState::default()).route("/a", get(|_: Extractor| async {}));
|
||||
let _: axum::routing::RouterService = Router::new()
|
||||
.route("/a", get(|_: Extractor| async {}))
|
||||
.with_state(AppState::default());
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, FromRequest)]
|
||||
|
||||
Reference in New Issue
Block a user