prosa_hyper/server/
adaptor.rs

1//! Hyper server adaptor definition
2use std::convert::Infallible;
3
4use bytes::Bytes;
5use http_body_util::{Full, combinators::BoxBody};
6use hyper::{Request, Response};
7use prosa::core::{adaptor::Adaptor, error::ProcError};
8
9use crate::HyperResp;
10
11use super::proc::HyperServerProc;
12
13#[cfg_attr(doc, aquamarine::aquamarine)]
14/// Trait to define the Hyper adaptor structure
15///
16/// ```mermaid
17/// graph LR
18///     IN[Input HTTP server]
19///     ProSA[ProSA Hyper Procesor]
20///
21///     IN-- HTTP request (process_server_request) -->ProSA
22///     ProSA-- HTTP response (process_server_response) -->IN
23/// ```
24pub trait HyperServerAdaptor<M>
25where
26    M: 'static
27        + std::marker::Send
28        + std::marker::Sync
29        + std::marker::Sized
30        + std::clone::Clone
31        + std::fmt::Debug
32        + prosa_utils::msg::tvf::Tvf
33        + std::default::Default,
34{
35    /// Server header value send by the server
36    #[cfg(target_family = "unix")]
37    const SERVER_HEADER: &'static str =
38        concat!("ProSA-Hyper/", env!("CARGO_PKG_VERSION"), " (Unix)");
39    #[cfg(target_family = "windows")]
40    const SERVER_HEADER: &'static str =
41        concat!("ProSA-Hyper/", env!("CARGO_PKG_VERSION"), " (Windows)");
42    #[cfg(all(not(target_family = "unix"), not(target_family = "windows")))]
43    const SERVER_HEADER: &'static str = concat!("ProSA-Hyper/", env!("CARGO_PKG_VERSION"));
44
45    /// Create a new adaptor
46    fn new(
47        proc: &HyperServerProc<M>,
48        prosa_name: &str,
49    ) -> Result<Self, Box<dyn ProcError + Send + Sync>>
50    where
51        Self: Sized;
52
53    /// Method to process input HTTP requests. Received by the ProSA through Hyper
54    fn process_http_request(
55        &self,
56        req: Request<hyper::body::Incoming>,
57    ) -> impl std::future::Future<Output = HyperResp<M>> + Send;
58
59    /// Method to process input response to respond with an Hyper HTTP response.
60    fn process_srv_response(&self, resp: &M) -> Response<BoxBody<Bytes, Infallible>>;
61}
62
63/// Hello adaptor for the Hyper server processor. Use to respond to a request with a simple hello message
64#[derive(Debug, Adaptor, Clone)]
65pub struct HelloHyperServerAdaptor {
66    hello_msg: String,
67}
68
69impl<M> HyperServerAdaptor<M> for HelloHyperServerAdaptor
70where
71    M: 'static
72        + std::marker::Send
73        + std::marker::Sync
74        + std::marker::Sized
75        + std::clone::Clone
76        + std::fmt::Debug
77        + prosa_utils::msg::tvf::Tvf
78        + std::default::Default,
79{
80    fn new(
81        _proc: &HyperServerProc<M>,
82        prosa_name: &str,
83    ) -> Result<Self, Box<dyn ProcError + Send + Sync>> {
84        Ok(HelloHyperServerAdaptor {
85            hello_msg: format!("Hello from {prosa_name}"),
86        })
87    }
88
89    async fn process_http_request(&self, _req: Request<hyper::body::Incoming>) -> HyperResp<M> {
90        HyperResp::<M>::HttpResp(
91            Response::builder()
92                .status(200)
93                .header(
94                    "Server",
95                    <HelloHyperServerAdaptor as HyperServerAdaptor<M>>::SERVER_HEADER,
96                )
97                .body(BoxBody::new(Full::new(Bytes::from(self.hello_msg.clone()))))
98                .unwrap(),
99        )
100    }
101
102    fn process_srv_response(&self, _resp: &M) -> Response<BoxBody<Bytes, Infallible>> {
103        panic!("No message should be send to an external service")
104    }
105}