spring_web/
extractor.rs

1pub use axum::extract::*;
2
3use crate::error::{Result, WebError};
4use crate::AppState;
5use anyhow::Context;
6use axum::http::request::Parts;
7use spring::config::{ConfigRegistry, Configurable};
8use spring::plugin::ComponentRegistry;
9use std::ops::{Deref, DerefMut};
10use std::result::Result as StdResult;
11
12/// Extending the functionality of RequestParts
13pub trait RequestPartsExt {
14    /// get AppState
15    fn get_app_state(&self) -> &AppState;
16
17    /// get Component
18    fn get_component<T: Clone + Send + Sync + 'static>(&self) -> Result<T>;
19
20    /// get Config
21    fn get_config<T: serde::de::DeserializeOwned + Configurable>(&self) -> Result<T>;
22}
23
24impl RequestPartsExt for Parts {
25    fn get_app_state(&self) -> &AppState {
26        self.extensions
27            .get::<AppState>()
28            .expect("extract app state from extension failed")
29    }
30
31    fn get_component<T: Clone + Send + Sync + 'static>(&self) -> Result<T> {
32        Ok(self
33            .get_app_state()
34            .app
35            .try_get_component()
36            .context("get_component failed")?)
37    }
38
39    fn get_config<T: serde::de::DeserializeOwned + Configurable>(&self) -> Result<T> {
40        self.get_app_state()
41            .app
42            .get_config::<T>()
43            .map_err(|e| WebError::ConfigDeserializeErr(std::any::type_name::<T>(), Box::new(e)))
44    }
45}
46
47/// Extract the components registered by the plugin from AppState
48pub struct Component<T: Clone>(pub T);
49
50impl<T, S> FromRequestParts<S> for Component<T>
51where
52    T: Clone + Send + Sync + 'static,
53    S: Sync,
54{
55    type Rejection = WebError;
56
57    async fn from_request_parts(parts: &mut Parts, _s: &S) -> StdResult<Self, Self::Rejection> {
58        parts.get_component::<T>().map(|c| Component(c))
59    }
60}
61
62#[cfg(feature = "openapi")]
63impl<T: Clone> aide::OperationInput for Component<T> {}
64
65impl<T: Clone> Deref for Component<T> {
66    type Target = T;
67
68    fn deref(&self) -> &Self::Target {
69        &self.0
70    }
71}
72
73impl<T: Clone> DerefMut for Component<T> {
74    fn deref_mut(&mut self) -> &mut Self::Target {
75        &mut self.0
76    }
77}
78
79pub struct Config<T>(pub T)
80where
81    T: serde::de::DeserializeOwned + Configurable;
82
83impl<T, S> FromRequestParts<S> for Config<T>
84where
85    T: serde::de::DeserializeOwned + Configurable,
86    S: Sync,
87{
88    type Rejection = WebError;
89
90    async fn from_request_parts(parts: &mut Parts, _s: &S) -> StdResult<Self, Self::Rejection> {
91        parts.get_config().map(|c| Config(c))
92    }
93}
94
95#[cfg(feature = "openapi")]
96impl<T> aide::OperationInput for Config<T> where T: serde::de::DeserializeOwned + Configurable {}
97
98impl<T> Deref for Config<T>
99where
100    T: serde::de::DeserializeOwned + Configurable,
101{
102    type Target = T;
103
104    fn deref(&self) -> &Self::Target {
105        &self.0
106    }
107}
108
109impl<T> DerefMut for Config<T>
110where
111    T: serde::de::DeserializeOwned + Configurable,
112{
113    fn deref_mut(&mut self) -> &mut Self::Target {
114        &mut self.0
115    }
116}