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