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
12pub trait RequestPartsExt {
14 fn get_app_state(&self) -> &AppState;
16
17 fn get_component<T: Clone + Send + Sync + 'static>(&self) -> Result<T>;
19
20 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
47pub 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
62impl<T: Clone> Deref for Component<T> {
63 type Target = T;
64
65 fn deref(&self) -> &Self::Target {
66 &self.0
67 }
68}
69
70impl<T: Clone> DerefMut for Component<T> {
71 fn deref_mut(&mut self) -> &mut Self::Target {
72 &mut self.0
73 }
74}
75
76pub struct Config<T>(pub T)
77where
78 T: serde::de::DeserializeOwned + Configurable;
79
80impl<T, S> FromRequestParts<S> for Config<T>
81where
82 T: serde::de::DeserializeOwned + Configurable,
83 S: Sync,
84{
85 type Rejection = WebError;
86
87 async fn from_request_parts(parts: &mut Parts, _s: &S) -> StdResult<Self, Self::Rejection> {
88 parts.get_config().map(|c| Config(c))
89 }
90}
91
92impl<T> Deref for Config<T>
93where
94 T: serde::de::DeserializeOwned + Configurable,
95{
96 type Target = T;
97
98 fn deref(&self) -> &Self::Target {
99 &self.0
100 }
101}
102
103impl<T> DerefMut for Config<T>
104where
105 T: serde::de::DeserializeOwned + Configurable,
106{
107 fn deref_mut(&mut self) -> &mut Self::Target {
108 &mut self.0
109 }
110}