Skip to main content

ansible_inventory_cloud/http/impl_axum/
host_handler.rs

1use 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
20//
21impl<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}