mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 14:54:16 +00:00
feat: support Axum extractors with state other than ()
(#1275)
This requires state to be provided via context using a special handler, but allows for extractors that use this state, rather than only `()`, as previously.
This commit is contained in:
parent
f06ffd72aa
commit
7e540a8f49
1 changed files with 53 additions and 10 deletions
|
@ -1276,18 +1276,24 @@ impl ExtractorHelper {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn extract<F, T, U>(&self, f: F) -> Result<U, T::Rejection>
|
||||
pub async fn extract<F, T, U, S>(
|
||||
&self,
|
||||
f: F,
|
||||
s: S,
|
||||
) -> Result<U, T::Rejection>
|
||||
where
|
||||
F: Extractor<T, U>,
|
||||
T: std::fmt::Debug + Send + FromRequestParts<()> + 'static,
|
||||
S: Sized,
|
||||
F: Extractor<T, U, S>,
|
||||
T: std::fmt::Debug + Send + FromRequestParts<S> + 'static,
|
||||
T::Rejection: std::fmt::Debug + Send + 'static,
|
||||
{
|
||||
let mut parts = self.parts.lock().await;
|
||||
let data = T::from_request_parts(&mut parts, &()).await?;
|
||||
let data = T::from_request_parts(&mut parts, &s).await?;
|
||||
Ok(f.call(data).await)
|
||||
}
|
||||
}
|
||||
|
||||
/// Getting ExtractorHelper from a request will return an ExtractorHelper whose state is ().
|
||||
impl<B> From<Request<B>> for ExtractorHelper {
|
||||
fn from(req: Request<B>) -> Self {
|
||||
// TODO provide body for extractors there, too?
|
||||
|
@ -1324,34 +1330,71 @@ impl<B> From<Request<B>> for ExtractorHelper {
|
|||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
pub async fn extract<T, U>(
|
||||
cx: Scope,
|
||||
f: impl Extractor<T, U>,
|
||||
f: impl Extractor<T, U, ()>,
|
||||
) -> Result<U, T::Rejection>
|
||||
where
|
||||
T: std::fmt::Debug + Send + FromRequestParts<()> + 'static,
|
||||
T::Rejection: std::fmt::Debug + Send + 'static,
|
||||
{
|
||||
extract_with_state(cx, (), f).await
|
||||
}
|
||||
|
||||
/// A helper to make it easier to use Axum extractors in server functions. This takes
|
||||
/// a handler function and state as its arguments. The handler rules similar to Axum
|
||||
/// [handlers](https://docs.rs/axum/latest/axum/extract/index.html#intro): it is an async function
|
||||
/// whose arguments are “extractors.”
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// #[server(QueryExtract, "/api")]
|
||||
/// pub async fn query_extract(cx: Scope) -> Result<String, ServerFnError> {
|
||||
/// use axum::{extract::Query, http::Method};
|
||||
/// use leptos_axum::extract;
|
||||
/// let state: ServerState = use_context::<crate::ServerState>(cx)
|
||||
/// .ok_or(ServerFnError::ServerError("No server state".to_string()))?;
|
||||
///
|
||||
/// extract_with_state(cx, state, |method: Method, res: Query<MyQuery>| async move {
|
||||
/// format!("{method:?} and {}", res.q)
|
||||
/// },
|
||||
/// )
|
||||
/// .await
|
||||
/// .map_err(|e| ServerFnError::ServerError("Could not extract method and query...".to_string()))
|
||||
/// }
|
||||
/// ```
|
||||
#[tracing::instrument(level = "trace", fields(error), skip_all)]
|
||||
pub async fn extract_with_state<T, U, S>(
|
||||
cx: Scope,
|
||||
state: S,
|
||||
f: impl Extractor<T, U, S>,
|
||||
) -> Result<U, T::Rejection>
|
||||
where
|
||||
S: Sized,
|
||||
T: std::fmt::Debug + Send + FromRequestParts<S> + 'static,
|
||||
T::Rejection: std::fmt::Debug + Send + 'static,
|
||||
{
|
||||
use_context::<ExtractorHelper>(cx)
|
||||
.expect(
|
||||
"should have had ExtractorHelper provided by the leptos_axum \
|
||||
integration",
|
||||
)
|
||||
.extract(f)
|
||||
.extract(f, state)
|
||||
.await
|
||||
}
|
||||
|
||||
pub trait Extractor<T, U>
|
||||
pub trait Extractor<T, U, S>
|
||||
where
|
||||
T: FromRequestParts<()>,
|
||||
S: Sized,
|
||||
T: FromRequestParts<S>,
|
||||
{
|
||||
fn call(self, args: T) -> Pin<Box<dyn Future<Output = U>>>;
|
||||
}
|
||||
|
||||
macro_rules! factory_tuple ({ $($param:ident)* } => {
|
||||
impl<Func, Fut, U, $($param,)*> Extractor<($($param,)*), U> for Func
|
||||
impl<Func, Fut, U, S, $($param,)*> Extractor<($($param,)*), U, S> for Func
|
||||
where
|
||||
$($param: FromRequestParts<()> + Send,)*
|
||||
$($param: FromRequestParts<S> + Send,)*
|
||||
Func: FnOnce($($param),*) -> Fut + 'static,
|
||||
Fut: Future<Output = U> + 'static,
|
||||
S: Sized + Send + Sync,
|
||||
{
|
||||
#[inline]
|
||||
#[allow(non_snake_case)]
|
||||
|
|
Loading…
Reference in a new issue