ansible_inventory_cloud/http/impl_axum/
host_handler.rs1use core::{future::Future, pin::Pin};
2
3use axum::{
4 body::Body,
5 extract::{FromRequestParts as _, Path, Query, TypedHeader},
6 handler::Handler,
7 headers::{authorization::Bearer, Authorization},
8 http::{Request, StatusCode},
9 response::{IntoResponse as _, Json, Response},
10};
11
12use crate::http::{
13 authentication::{
14 Authentication, AuthenticationQuery, AuthenticationType, AuthenticationVerifier,
15 },
16 host_handler::{Fetcher, HostHandler},
17 hostname::{Hostname, HostnameAxumPath, HostnameQuery, HostnameType},
18};
19
20impl<T, S, AQ, AO, HAP, HQ, Ctx> Handler<T, S, Body> for HostHandler<AQ, AO, HAP, HQ, Ctx>
22where
23 S: Send + Sync + 'static,
24 AQ: AuthenticationQuery + Send + 'static,
25 AO: Send + 'static,
26 HAP: HostnameAxumPath + Send + 'static,
27 HQ: HostnameQuery + Send + 'static,
28 Ctx: Clone + Send + Sync + 'static,
29{
30 type Future = Pin<Box<dyn Future<Output = Response> + Send + 'static>>;
31
32 fn call(self, req: Request<Body>, state: S) -> Self::Future {
33 Box::pin(async move {
34 let (mut parts, _) = req.into_parts();
35
36 let mut authentication = None;
37 for authentication_type in self.authentication_types {
38 match authentication_type {
39 AuthenticationType::HeaderAuthorizationBearer => {
40 if let Ok(bearer) =
41 TypedHeader::<Authorization<Bearer>>::from_request_parts(
42 &mut parts, &state,
43 )
44 .await
45 {
46 authentication = Some(Authentication::HeaderAuthorizationBearer(
47 bearer.token().into(),
48 ));
49 }
50 }
51 AuthenticationType::Query => {
52 if let Ok(Query(query)) =
53 Query::<AQ>::from_request_parts(&mut parts, &state).await
54 {
55 authentication = Some(Authentication::Query(query));
56 }
57 }
58 }
59 }
60 let authentication = if let Some(authentication) = authentication {
61 authentication
62 } else {
63 return (
64 StatusCode::INTERNAL_SERVER_ERROR,
65 "authentication not found",
66 )
67 .into_response();
68 };
69
70 let mut hostname = None;
71 for hostname_type in self.hostname_types {
72 match hostname_type {
73 HostnameType::AxumPath => {
74 if let Ok(Path(path)) =
75 Path::<HAP>::from_request_parts(&mut parts, &state).await
76 {
77 hostname = Some(Hostname::AxumPath(path));
78 }
79 }
80 HostnameType::Query => {
81 if let Ok(Query(query)) =
82 Query::<HQ>::from_request_parts(&mut parts, &state).await
83 {
84 hostname = Some(Hostname::Query(query));
85 }
86 }
87 }
88 }
89 let hostname = if let Some(hostname) = hostname {
90 hostname
91 } else {
92 return (StatusCode::INTERNAL_SERVER_ERROR, "hostname not found").into_response();
93 };
94
95 let v = match &self.authentication_verifier {
96 AuthenticationVerifier::Sync(f) => match f(authentication, self.ctx.clone()) {
97 Ok(x) => x,
98 Err(err) => {
99 return (
100 StatusCode::INTERNAL_SERVER_ERROR,
101 format!("authentication verify failed, err:{err}"),
102 )
103 .into_response();
104 }
105 },
106 AuthenticationVerifier::Async(f) => match f(authentication, self.ctx.clone()).await
107 {
108 Ok(x) => x,
109 Err(err) => {
110 return (
111 StatusCode::INTERNAL_SERVER_ERROR,
112 format!("authentication verify failed, err:{err}"),
113 )
114 .into_response();
115 }
116 },
117 };
118
119 let host = match &self.fetcher {
120 Fetcher::Async(f) => match f(hostname, v, self.ctx.clone()).await {
121 Ok(x) => x,
122 Err(err) => {
123 return (
124 StatusCode::INTERNAL_SERVER_ERROR,
125 format!("fetch failed, err:{err}"),
126 )
127 .into_response();
128 }
129 },
130 };
131
132 Json(host).into_response()
133 })
134 }
135}