Files
axum/axum-core/src/ext_traits/request_parts.rs
T

109 lines
2.8 KiB
Rust
Raw Normal View History

use crate::extract::FromRequestParts;
2022-08-22 18:34:46 +02:00
use futures_util::future::BoxFuture;
use http::request::Parts;
mod sealed {
pub trait Sealed {}
impl Sealed for http::request::Parts {}
}
/// Extension trait that adds additional methods to [`Parts`].
pub trait RequestPartsExt: sealed::Sealed + Sized {
/// Apply an extractor to this `Parts`.
///
/// This is just a convenience for `E::from_request_parts(parts, &())`.
fn extract<E>(&mut self) -> BoxFuture<'_, Result<E, E::Rejection>>
where
E: FromRequestParts<()> + 'static;
/// Apply an extractor that requires some state to this `Parts`.
///
/// This is just a convenience for `E::from_request_parts(parts, state)`.
fn extract_with_state<'a, E, S>(
&'a mut self,
state: &'a S,
) -> BoxFuture<'a, Result<E, E::Rejection>>
where
E: FromRequestParts<S> + 'static,
S: Send + Sync;
}
impl RequestPartsExt for Parts {
fn extract<E>(&mut self) -> BoxFuture<'_, Result<E, E::Rejection>>
where
E: FromRequestParts<()> + 'static,
{
self.extract_with_state(&())
}
fn extract_with_state<'a, E, S>(
&'a mut self,
state: &'a S,
) -> BoxFuture<'a, Result<E, E::Rejection>>
where
E: FromRequestParts<S> + 'static,
S: Send + Sync,
{
E::from_request_parts(self, state)
}
}
#[cfg(test)]
mod tests {
use std::convert::Infallible;
use super::*;
use crate::{
ext_traits::tests::{RequiresState, State},
extract::FromRef,
};
2022-08-22 18:34:46 +02:00
use async_trait::async_trait;
use http::{Method, Request};
#[tokio::test]
async fn extract_without_state() {
let (mut parts, _) = Request::new(()).into_parts();
let method: Method = parts.extract().await.unwrap();
assert_eq!(method, Method::GET);
}
#[tokio::test]
async fn extract_with_state() {
let (mut parts, _) = Request::new(()).into_parts();
let state = "state".to_owned();
let State(extracted_state): State<String> = parts
.extract_with_state::<State<String>, String>(&state)
.await
.unwrap();
2022-08-22 18:34:46 +02:00
assert_eq!(extracted_state, state);
}
// this stuff just needs to compile
#[allow(dead_code)]
struct WorksForCustomExtractor {
method: Method,
from_state: String,
}
#[async_trait]
impl<S> FromRequestParts<S> for WorksForCustomExtractor
where
S: Send + Sync,
String: FromRef<S>,
{
type Rejection = Infallible;
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
let RequiresState(from_state) = parts.extract_with_state(state).await?;
let method = parts.extract().await?;
Ok(Self { method, from_state })
}
}
}