redfish_axum/
cooling_loop.rs1pub struct CoolingLoop<S, P>
8where
9 S: Clone,
10{
11 router: axum::routing::MethodRouter<S>,
12 privilege_marker: std::marker::PhantomData<fn() -> P>,
13 allowed_methods: Vec<axum::http::method::Method>,
14}
15
16
17impl<S, P> CoolingLoop<S, P>
18where
19 S: AsRef<dyn redfish_core::auth::AuthenticateRequest> + Clone + Send + Sync + 'static,
20 P: redfish_core::privilege::OperationPrivilegeMapping + 'static,
21 <P as redfish_core::privilege::OperationPrivilegeMapping>::Get: Send,
22 <P as redfish_core::privilege::OperationPrivilegeMapping>::Put: Send,
23 <P as redfish_core::privilege::OperationPrivilegeMapping>::Patch: Send,
24{
25 pub fn get<H, T>(mut self, handler: H) -> Self
26 where
27 H: axum::handler::Handler<T, S, axum::body::Body>,
28 T: 'static,
29 {
30 let operation = axum::routing::get(
31 |auth: redfish_core::extract::RedfishAuth<P::Get>,
32 axum::extract::State(state): axum::extract::State<S>,
33 mut request: axum::http::Request<axum::body::Body>| async {
34 request.extensions_mut().insert(auth.user);
35 handler.call(request, state).await
36 },
37 );
38 self.router = self.router.get(operation);
39 self.allowed_methods.push(axum::http::method::Method::GET);
40 self
41 }
42
43 pub fn put<H, T>(mut self, handler: H) -> Self
44 where
45 H: axum::handler::Handler<T, S, axum::body::Body>,
46 T: 'static,
47 {
48 let operation = axum::routing::put(
49 |auth: redfish_core::extract::RedfishAuth<P::Put>,
50 axum::extract::State(state): axum::extract::State<S>,
51 mut request: axum::http::Request<axum::body::Body>| async {
52 request.extensions_mut().insert(auth.user);
53 handler.call(request, state).await
54 },
55 );
56 self.router = self.router.put(operation);
57 self.allowed_methods.push(axum::http::method::Method::PUT);
58 self
59 }
60
61 pub fn patch<H, T>(mut self, handler: H) -> Self
62 where
63 H: axum::handler::Handler<T, S, axum::body::Body>,
64 T: 'static,
65 {
66 let operation = axum::routing::patch(
67 |auth: redfish_core::extract::RedfishAuth<P::Patch>,
68 axum::extract::State(state): axum::extract::State<S>,
69 mut request: axum::http::Request<axum::body::Body>| async {
70 request.extensions_mut().insert(auth.user);
71 handler.call(request, state).await
72 },
73 );
74 self.router = self.router.patch(operation);
75 self.allowed_methods.push(axum::http::method::Method::PATCH);
76 self
77 }
78
79 pub fn into_router(self) -> axum::Router<S> {
80 let Self {
81 router,
82 mut allowed_methods,
83 ..
84 } = self;
85 let result = axum::Router::default();
86 allowed_methods.dedup();
87 let allow_header = allowed_methods
88 .into_iter()
89 .map(|method| method.to_string())
90 .reduce(|one, two| one + "," + &two)
91 .unwrap();
92 result.route(
93 "/",
94 router.fallback(|| async {
95 (
96 axum::http::StatusCode::METHOD_NOT_ALLOWED,
97 axum::Json(redfish_core::error::one_message(redfish_codegen::registries::base::v1_16_0::Base::OperationNotAllowed.into())),
98 )
99 })
100 .route_layer(axum::middleware::from_fn_with_state(
101 allow_header,
102 |axum::extract::State(allow_header): axum::extract::State<String>,
103 request: axum::http::Request<axum::body::Body>,
104 next: axum::middleware::Next<axum::body::Body>| async move {
105 let apply_allow = matches!(*request.method(), axum::http::Method::GET | axum::http::Method::HEAD);
106 let mut response = next.run(request).await;
107 if apply_allow && !response.headers().contains_key(axum::http::header::ALLOW) {
108 response.headers_mut().insert(
109 axum::http::header::ALLOW,
110 axum::http::HeaderValue::from_str(&allow_header).unwrap(),
111 );
112 }
113 response
114 },
115 )),
116 )
117 }
118}