mirror of
https://github.com/tokio-rs/axum.git
synced 2026-08-28 00:00:20 +02:00
fix some todos
This commit is contained in:
@@ -22,8 +22,6 @@ use tower_service::Service;
|
||||
/// that handles errors by converting them into responses.
|
||||
///
|
||||
/// See [module docs](self) for more details on axum's error handling model.
|
||||
// TODO(david): cannot access state, is that bad? It leads to inference issues and one has to
|
||||
// specify the type manually and risk getting it wrong. So its basically an Extension at that point
|
||||
pub struct HandleErrorLayer<F, T> {
|
||||
f: F,
|
||||
_extractor: PhantomData<fn() -> T>,
|
||||
|
||||
@@ -2,8 +2,7 @@ use super::{FromRequest, RequestParts};
|
||||
use async_trait::async_trait;
|
||||
use std::convert::Infallible;
|
||||
|
||||
/// TODO(david): docs
|
||||
// TODO(david): document how to extract this from middleware
|
||||
// document how to extract this from middleware
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct State<S>(pub S);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use super::Handler;
|
||||
use crate::{extract::State, response::Response};
|
||||
use crate::{response::Response, util::extract_state_assume_present};
|
||||
use http::Request;
|
||||
use std::{
|
||||
convert::Infallible,
|
||||
@@ -59,18 +59,7 @@ where
|
||||
|
||||
let handler = self.handler.clone();
|
||||
|
||||
// TODO(david): this is duplicated in `axum/src/routing/mod.rs`
|
||||
// extract into helper function
|
||||
let State(state) = req
|
||||
.extensions()
|
||||
.get::<State<S>>()
|
||||
.unwrap_or_else(|| {
|
||||
panic!(
|
||||
"no state of type `{}` was found. Please file an issue",
|
||||
std::any::type_name::<State<S>>()
|
||||
)
|
||||
})
|
||||
.clone();
|
||||
let state = extract_state_assume_present::<S, _>(&req);
|
||||
let future = Handler::call(handler, state, req);
|
||||
let future = future.map(Ok as _);
|
||||
|
||||
|
||||
@@ -64,8 +64,7 @@ pub mod future;
|
||||
/// See the [module docs](crate::handler) for more details.
|
||||
///
|
||||
#[doc = include_str!("../docs/debugging_handler_type_errors.md")]
|
||||
// TODO(david): Add back `B = Body` default
|
||||
pub trait Handler<S, T, B>: Clone + Send + Sized + 'static {
|
||||
pub trait Handler<S, T, B = Body>: Clone + Send + Sized + 'static {
|
||||
/// The type of future calling this handler returns.
|
||||
type Future: Future<Output = Response> + Send + 'static;
|
||||
|
||||
@@ -151,7 +150,6 @@ pub trait Handler<S, T, B>: Clone + Send + Sized + 'static {
|
||||
/// ```
|
||||
///
|
||||
/// [`Router::fallback`]: crate::routing::Router::fallback
|
||||
// TODO(david): remove this
|
||||
fn into_service(self, state: S) -> IntoService<Self, S, T, B> {
|
||||
IntoService::new(self, state)
|
||||
}
|
||||
@@ -179,7 +177,6 @@ pub trait Handler<S, T, B>: Clone + Send + Sized + 'static {
|
||||
/// ```
|
||||
///
|
||||
/// [`MakeService`]: tower::make::MakeService
|
||||
// TODO(david): remove this
|
||||
fn into_make_service(self, state: S) -> IntoMakeService<IntoService<Self, S, T, B>> {
|
||||
IntoMakeService::new(self.into_service(state))
|
||||
}
|
||||
@@ -212,7 +209,6 @@ pub trait Handler<S, T, B>: Clone + Send + Sized + 'static {
|
||||
///
|
||||
/// [`MakeService`]: tower::make::MakeService
|
||||
/// [`Router::into_make_service_with_connect_info`]: crate::routing::Router::into_make_service_with_connect_info
|
||||
// TODO(david): remove this
|
||||
fn into_make_service_with_connect_info<C>(
|
||||
self,
|
||||
state: S,
|
||||
@@ -350,16 +346,20 @@ where
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::test_helpers::*;
|
||||
use crate::{extract::State, test_helpers::*};
|
||||
use http::StatusCode;
|
||||
|
||||
#[tokio::test]
|
||||
async fn handler_into_service() {
|
||||
async fn handle(body: String) -> impl IntoResponse {
|
||||
async fn handle(State(state): State<AppState>, body: String) -> impl IntoResponse {
|
||||
assert_eq!(state.0, 1337);
|
||||
format!("you said: {}", body)
|
||||
}
|
||||
|
||||
let client = TestClient::new(handle.into_service(()));
|
||||
#[derive(Clone)]
|
||||
struct AppState(i32);
|
||||
|
||||
let client = TestClient::new(handle.into_service(AppState(1337)));
|
||||
|
||||
let res = client.post("/").body("hi there!").send().await;
|
||||
assert_eq!(res.status(), StatusCode::OK);
|
||||
|
||||
+2
-2
@@ -382,8 +382,8 @@
|
||||
rust_2018_idioms,
|
||||
future_incompatible,
|
||||
nonstandard_style,
|
||||
// missing_debug_implementations,
|
||||
// missing_docs
|
||||
missing_debug_implementations,
|
||||
missing_docs
|
||||
)]
|
||||
#![deny(unreachable_pub, private_in_public)]
|
||||
#![allow(elided_lifetimes_in_paths, clippy::type_complexity)]
|
||||
|
||||
@@ -400,7 +400,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn extracting_state() {
|
||||
async fn access_state<B>(req: Request<B>, next: Next<B>) -> impl IntoResponse {
|
||||
async fn access_state<B>(req: Request<B>, _next: Next<B>) -> impl IntoResponse {
|
||||
let State(state) = req.extensions().get::<State<AppState>>().unwrap().clone();
|
||||
state.value
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ impl<T> From<T> for Html<T> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::extract::Extension;
|
||||
use crate::{body::Body, routing::get, Router};
|
||||
use crate::{routing::get, Router};
|
||||
use axum_core::response::IntoResponse;
|
||||
use http::HeaderMap;
|
||||
use http::{StatusCode, Uri};
|
||||
|
||||
@@ -76,7 +76,7 @@ macro_rules! top_level_service_fn {
|
||||
$name:ident, $method:ident
|
||||
) => {
|
||||
$(#[$m])+
|
||||
pub fn $name<T, ReqBody, ResBody, S>(svc: T) -> MethodRouter<S, ReqBody, T::Error, MissingState>
|
||||
pub fn $name<T, ReqBody, ResBody, S>(svc: T) -> MethodRouter<S, MissingState, ReqBody, T::Error>
|
||||
where
|
||||
T: Service<Request<ReqBody>, Response = Response<ResBody>> + Clone + Send + 'static,
|
||||
T::Future: Send + 'static,
|
||||
@@ -137,7 +137,7 @@ macro_rules! top_level_handler_fn {
|
||||
$name:ident, $method:ident
|
||||
) => {
|
||||
$(#[$m])+
|
||||
pub fn $name<H, S, T, B>(handler: H) -> MethodRouter<S, B, Infallible, MissingState>
|
||||
pub fn $name<H, S, T, B>(handler: H) -> MethodRouter<S, MissingState, B, Infallible>
|
||||
where
|
||||
H: Handler<S, T, B>,
|
||||
B: Send + 'static,
|
||||
@@ -321,7 +321,7 @@ top_level_service_fn!(trace_service, TRACE);
|
||||
pub fn on_service<T, ReqBody, ResBody, S>(
|
||||
filter: MethodFilter,
|
||||
svc: T,
|
||||
) -> MethodRouter<S, ReqBody, T::Error, MissingState>
|
||||
) -> MethodRouter<S, MissingState, ReqBody, T::Error>
|
||||
where
|
||||
T: Service<Request<ReqBody>, Response = Response<ResBody>> + Clone + Send + 'static,
|
||||
T::Future: Send + 'static,
|
||||
@@ -386,7 +386,7 @@ where
|
||||
/// ```
|
||||
pub fn any_service<T, ReqBody, ResBody, S>(
|
||||
svc: T,
|
||||
) -> MethodRouter<S, ReqBody, T::Error, MissingState>
|
||||
) -> MethodRouter<S, MissingState, ReqBody, T::Error>
|
||||
where
|
||||
T: Service<Request<ReqBody>, Response = Response<ResBody>> + Clone + Send + 'static,
|
||||
T::Future: Send + 'static,
|
||||
@@ -429,7 +429,7 @@ top_level_handler_fn!(trace, TRACE);
|
||||
pub fn on<H, S, T, B>(
|
||||
filter: MethodFilter,
|
||||
handler: H,
|
||||
) -> MethodRouter<S, B, Infallible, MissingState>
|
||||
) -> MethodRouter<S, MissingState, B, Infallible>
|
||||
where
|
||||
H: Handler<S, T, B>,
|
||||
B: Send + 'static,
|
||||
@@ -476,7 +476,7 @@ where
|
||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
||||
/// # };
|
||||
/// ```
|
||||
pub fn any<H, S, T, B>(handler: H) -> MethodRouter<S, B, Infallible, MissingState>
|
||||
pub fn any<H, S, T, B>(handler: H) -> MethodRouter<S, MissingState, B, Infallible>
|
||||
where
|
||||
H: Handler<S, T, B>,
|
||||
B: Send + 'static,
|
||||
@@ -490,9 +490,7 @@ where
|
||||
|
||||
/// A [`Service`] that accepts requests based on a [`MethodFilter`] and
|
||||
/// allows chaining additional handlers and services.
|
||||
// TODO(david): Bring back `B = Body, E = Infallible` defaults
|
||||
// TODO(david): think about ordering of type params here
|
||||
pub struct MethodRouter<S, B, E, R> {
|
||||
pub struct MethodRouter<S, R = MissingState, B = Body, E = Infallible> {
|
||||
// Invariant: If `R == MissingState` then `state` is `None`
|
||||
// If `R == WithState` then state is `Some`
|
||||
// `R` cannot have other values
|
||||
@@ -520,7 +518,7 @@ enum AllowHeader {
|
||||
Bytes(BytesMut),
|
||||
}
|
||||
|
||||
impl<S, B, E, R> fmt::Debug for MethodRouter<S, B, E, R>
|
||||
impl<S, B, E, R> fmt::Debug for MethodRouter<S, R, B, E>
|
||||
where
|
||||
S: fmt::Debug,
|
||||
{
|
||||
@@ -540,7 +538,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, B, E> MethodRouter<S, B, E, MissingState> {
|
||||
impl<S, B, E> MethodRouter<S, MissingState, B, E> {
|
||||
/// Create a default `MethodRouter` that will respond with `405 Method Not Allowed` to all
|
||||
/// requests.
|
||||
pub fn new() -> Self {
|
||||
@@ -566,8 +564,7 @@ impl<S, B, E> MethodRouter<S, B, E, MissingState> {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO(david): docs
|
||||
pub fn state(self, state: S) -> MethodRouter<S, B, E, WithState> {
|
||||
pub fn state(self, state: S) -> MethodRouter<S, WithState, B, E> {
|
||||
MethodRouter {
|
||||
state: Some(state),
|
||||
get: self.get,
|
||||
@@ -585,21 +582,19 @@ impl<S, B, E> MethodRouter<S, B, E, MissingState> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, B, E> MethodRouter<S, B, E, WithState> {
|
||||
/// TODO(david): docs
|
||||
impl<S, B, E> MethodRouter<S, WithState, B, E> {
|
||||
pub fn with_state(state: S) -> Self {
|
||||
MethodRouter::new().state(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, E> MethodRouter<(), B, E, WithState> {
|
||||
/// TODO(david): docs
|
||||
impl<B, E> MethodRouter<(), WithState, B, E> {
|
||||
pub fn without_state() -> Self {
|
||||
MethodRouter::with_state(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, B, R> MethodRouter<S, B, Infallible, R>
|
||||
impl<S, B, R> MethodRouter<S, R, B, Infallible>
|
||||
where
|
||||
B: Send + 'static,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
@@ -645,7 +640,7 @@ where
|
||||
chained_handler_fn!(trace, TRACE);
|
||||
|
||||
#[doc = include_str!("../docs/routing/fallback.md")]
|
||||
pub fn fallback<H, T>(mut self, handler: H) -> Self
|
||||
pub fn fallback<H, T>(self, handler: H) -> Self
|
||||
where
|
||||
H: Handler<S, T, B>,
|
||||
T: 'static,
|
||||
@@ -654,8 +649,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, B, R> MethodRouter<S, B, Infallible, R> {
|
||||
pub(crate) fn change_state_marker<R2>(self) -> MethodRouter<S, B, Infallible, R2> {
|
||||
impl<S, B, R> MethodRouter<S, R, B, Infallible> {
|
||||
pub(crate) fn change_state_marker<R2>(self) -> MethodRouter<S, R2, B, Infallible> {
|
||||
MethodRouter {
|
||||
state: self.state,
|
||||
get: self.get,
|
||||
@@ -673,8 +668,8 @@ impl<S, B, R> MethodRouter<S, B, Infallible, R> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, B> MethodRouter<S, B, Infallible, MissingState> {
|
||||
pub(crate) fn change_state<S2>(self) -> MethodRouter<S2, B, Infallible, MissingState> {
|
||||
impl<S, B> MethodRouter<S, MissingState, B, Infallible> {
|
||||
pub(crate) fn change_state<S2>(self) -> MethodRouter<S2, MissingState, B, Infallible> {
|
||||
debug_assert!(self.state.is_none());
|
||||
MethodRouter {
|
||||
state: None,
|
||||
@@ -693,7 +688,7 @@ impl<S, B> MethodRouter<S, B, Infallible, MissingState> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, B> MethodRouter<S, B, Infallible, WithState>
|
||||
impl<S, B> MethodRouter<S, WithState, B, Infallible>
|
||||
where
|
||||
B: Send + 'static,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
@@ -767,7 +762,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, B, E, R> MethodRouter<S, B, E, R> {
|
||||
impl<S, B, E, R> MethodRouter<S, R, B, E> {
|
||||
/// Chain an additional service that will accept requests matching the given
|
||||
/// `MethodFilter`.
|
||||
///
|
||||
@@ -837,7 +832,7 @@ impl<S, B, E, R> MethodRouter<S, B, E, R> {
|
||||
pub fn layer<L, NewReqBody, NewResBody, NewError>(
|
||||
self,
|
||||
layer: L,
|
||||
) -> MethodRouter<S, NewReqBody, NewError, R>
|
||||
) -> MethodRouter<S, R, NewReqBody, NewError>
|
||||
where
|
||||
L: Layer<Route<B, E>>,
|
||||
L::Service: Service<Request<NewReqBody>, Response = Response<NewResBody>, Error = NewError>
|
||||
@@ -872,7 +867,7 @@ impl<S, B, E, R> MethodRouter<S, B, E, R> {
|
||||
}
|
||||
|
||||
#[doc = include_str!("../docs/method_routing/route_layer.md")]
|
||||
pub fn route_layer<L, NewResBody>(self, layer: L) -> MethodRouter<S, B, E, R>
|
||||
pub fn route_layer<L, NewResBody>(self, layer: L) -> MethodRouter<S, R, B, E>
|
||||
where
|
||||
L: Layer<Route<B, E>>,
|
||||
L::Service: Service<Request<B>, Response = Response<NewResBody>, Error = E>
|
||||
@@ -907,7 +902,7 @@ impl<S, B, E, R> MethodRouter<S, B, E, R> {
|
||||
}
|
||||
|
||||
#[doc = include_str!("../docs/method_routing/merge.md")]
|
||||
pub fn merge(self, other: MethodRouter<S, B, E, MissingState>) -> Self {
|
||||
pub fn merge(self, other: MethodRouter<S, MissingState, B, E>) -> Self {
|
||||
macro_rules! merge {
|
||||
( $first:ident, $second:ident ) => {
|
||||
match ($first, $second) {
|
||||
@@ -1003,7 +998,7 @@ impl<S, B, E, R> MethodRouter<S, B, E, R> {
|
||||
/// Apply a [`HandleErrorLayer`].
|
||||
///
|
||||
/// This is a convenience method for doing `self.layer(HandleErrorLayer::new(f))`.
|
||||
pub fn handle_error<F, T>(self, f: F) -> MethodRouter<S, B, Infallible, R>
|
||||
pub fn handle_error<F, T>(self, f: F) -> MethodRouter<S, R, B, Infallible>
|
||||
where
|
||||
F: Clone + Send + 'static,
|
||||
HandleError<Route<B, E>, F, T>:
|
||||
@@ -1120,7 +1115,7 @@ fn append_allow_header(allow_header: &mut AllowHeader, method: &'static str) {
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, B, E, R> Clone for MethodRouter<S, B, E, R>
|
||||
impl<S, B, E, R> Clone for MethodRouter<S, R, B, E>
|
||||
where
|
||||
S: Clone,
|
||||
{
|
||||
@@ -1142,7 +1137,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, B, E> Default for MethodRouter<S, B, E, MissingState>
|
||||
impl<S, B, E> Default for MethodRouter<S, MissingState, B, E>
|
||||
where
|
||||
B: Send + 'static,
|
||||
{
|
||||
@@ -1151,7 +1146,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, B, E> Service<Request<B>> for MethodRouter<S, B, E, WithState>
|
||||
impl<S, B, E> Service<Request<B>> for MethodRouter<S, WithState, B, E>
|
||||
where
|
||||
B: HttpBody,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
@@ -1430,7 +1425,7 @@ mod tests {
|
||||
expected = "Overlapping method route. Cannot add two method routes that both handle `GET`"
|
||||
)]
|
||||
async fn handler_overlaps() {
|
||||
let _: MethodRouter<(), Body, Infallible, _> = get(ok).get(ok);
|
||||
let _: MethodRouter<(), _, Body, Infallible> = get(ok).get(ok);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -1438,18 +1433,18 @@ mod tests {
|
||||
expected = "Overlapping method route. Cannot add two method routes that both handle `POST`"
|
||||
)]
|
||||
async fn service_overlaps() {
|
||||
let _: MethodRouter<(), Body, Infallible, _> =
|
||||
let _: MethodRouter<(), _, Body, Infallible> =
|
||||
post_service(ok.into_service(())).post_service(ok.into_service(()));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn get_head_does_not_overlap() {
|
||||
let _: MethodRouter<(), Body, Infallible, _> = get(ok).head(ok);
|
||||
let _: MethodRouter<(), _, Body, Infallible> = get(ok).head(ok);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn head_get_does_not_overlap() {
|
||||
let _: MethodRouter<(), Body, Infallible, _> = head(ok).get(ok);
|
||||
let _: MethodRouter<(), _, Body, Infallible> = head(ok).get(ok);
|
||||
}
|
||||
|
||||
async fn call<S>(method: Method, svc: &mut S) -> (StatusCode, HeaderMap, String)
|
||||
|
||||
+6
-23
@@ -7,7 +7,7 @@ use crate::{
|
||||
handler::{Handler, IntoExtensionService},
|
||||
response::Response,
|
||||
routing::strip_prefix::StripPrefix,
|
||||
util::try_downcast,
|
||||
util::{extract_state_assume_present, try_downcast},
|
||||
BoxError,
|
||||
};
|
||||
use http::Request;
|
||||
@@ -207,23 +207,9 @@ where
|
||||
_marker: PhantomData,
|
||||
}
|
||||
.layer(MapRequestLayer::new(move |mut req: Request<_>| {
|
||||
// TODO(david): this is duplicated in `axum/src/handler/into_extension_service.rs`
|
||||
// extract into helper function
|
||||
let State(outer_state) = req
|
||||
.extensions()
|
||||
.get::<State<OuterState>>()
|
||||
.unwrap_or_else(|| {
|
||||
panic!(
|
||||
"no state of type `{}` was found. Please file an issue",
|
||||
std::any::type_name::<State<OuterState>>()
|
||||
)
|
||||
})
|
||||
.clone();
|
||||
|
||||
let outer_state = extract_state_assume_present::<OuterState, _>(&req);
|
||||
let inner_state = f(outer_state);
|
||||
|
||||
req.extensions_mut().insert(State(inner_state));
|
||||
|
||||
req
|
||||
}))
|
||||
}
|
||||
@@ -234,7 +220,6 @@ where
|
||||
B: HttpBody + Send + 'static,
|
||||
S: Clone,
|
||||
{
|
||||
/// TODO(david): docs
|
||||
pub fn with_state(state: S) -> Self {
|
||||
Router::new().state(state)
|
||||
}
|
||||
@@ -244,7 +229,6 @@ impl<B> Router<(), WithState, B>
|
||||
where
|
||||
B: HttpBody + Send + 'static,
|
||||
{
|
||||
/// TODO(david): docs
|
||||
pub fn without_state() -> Self {
|
||||
Router::with_state(())
|
||||
}
|
||||
@@ -262,7 +246,7 @@ where
|
||||
path: &str,
|
||||
// TODO(david): constrain this so it only accepts methods
|
||||
// routers containing handlers
|
||||
method_router: MethodRouter<S, B, Infallible, MissingState>,
|
||||
method_router: MethodRouter<S, MissingState, B, Infallible>,
|
||||
) -> Self {
|
||||
validate_path_for_route(path);
|
||||
|
||||
@@ -301,7 +285,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO(david): docs
|
||||
pub fn route_service<T>(mut self, path: &str, service: T) -> Self
|
||||
where
|
||||
T: Service<Request<B>, Response = Response, Error = Infallible> + Clone + Send + 'static,
|
||||
@@ -530,8 +513,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(david): update docs
|
||||
#[doc = include_str!("../docs/routing/fallback.md")]
|
||||
pub fn fallback<H, T>(mut self, handler: H) -> Self
|
||||
pub fn fallback<H, T>(self, handler: H) -> Self
|
||||
where
|
||||
H: Handler<S, T, B>,
|
||||
T: 'static,
|
||||
@@ -540,7 +524,6 @@ where
|
||||
self.fallback_service(IntoExtensionService::new(handler))
|
||||
}
|
||||
|
||||
/// TODO(david): docs
|
||||
pub fn fallback_service<T>(mut self, svc: T) -> Self
|
||||
where
|
||||
T: Service<Request<B>, Response = Response, Error = Infallible> + Clone + Send + 'static,
|
||||
@@ -786,7 +769,7 @@ impl<B, E> Fallback<B, E> {
|
||||
}
|
||||
|
||||
enum Endpoint<S, R, B> {
|
||||
MethodRouter(MethodRouter<S, B, Infallible, R>),
|
||||
MethodRouter(MethodRouter<S, R, B, Infallible>),
|
||||
Route(Route<B>),
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
use http::Request;
|
||||
use pin_project_lite::pin_project;
|
||||
use std::{ops::Deref, sync::Arc};
|
||||
|
||||
use crate::extract::State;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub(crate) struct PercentDecodedStr(Arc<str>);
|
||||
|
||||
@@ -54,6 +57,27 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract the state from request extensions and panic if its not there.
|
||||
///
|
||||
/// This should only be called after `Router::call` or `MethodRouter::call` have been called.
|
||||
pub(crate) fn extract_state_assume_present<S, B>(req: &Request<B>) -> S
|
||||
where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
let State(state) = req
|
||||
.extensions()
|
||||
.get::<State<S>>()
|
||||
.unwrap_or_else(|| {
|
||||
panic!(
|
||||
"no state of type `{}` was found. Please file an issue",
|
||||
std::any::type_name::<State<S>>()
|
||||
)
|
||||
})
|
||||
.clone();
|
||||
|
||||
state
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_downcast() {
|
||||
assert_eq!(try_downcast::<i32, _>(5_u32), Err(5_u32));
|
||||
|
||||
Reference in New Issue
Block a user