cat_gateway/service/utilities/middleware/
node_info.rs

1//! Adds an information about the running cat-gateway instance for each response headers.
2
3use std::fmt::Write;
4
5use poem::{Endpoint, IntoResponse, Middleware, Request, Response, Result};
6
7use crate::{
8    build_info::build_info,
9    settings::{self, Settings},
10};
11
12/// A prefix for any custom header field <https://datatracker.ietf.org/doc/html/rfc6648#appendix-B>
13const CUSTOM_HEADER_PREFIX: &str = "VND.projectcatalyst.io";
14
15/// Middleware type that returns a response with 503 status code
16/// if any DB stops responding before returning the wrapped endpoint.
17pub(crate) struct CatGatewayInfo;
18
19impl<E: Endpoint> Middleware<E> for CatGatewayInfo {
20    type Output = CatGatewayInfoImpl<E>;
21
22    fn transform(
23        &self,
24        ep: E,
25    ) -> Self::Output {
26        CatGatewayInfoImpl { ep }
27    }
28}
29
30/// The new endpoint type generated by the `CatGatewayInfo`.
31pub(crate) struct CatGatewayInfoImpl<E> {
32    /// Endpoint wrapped by the middleware.
33    ep: E,
34}
35
36impl<E: Endpoint> Endpoint for CatGatewayInfoImpl<E> {
37    type Output = Response;
38
39    async fn call(
40        &self,
41        req: Request,
42    ) -> Result<Self::Output> {
43        let resp = self.ep.call(req).await?.into_response();
44
45        Ok(resp
46            // using a `Server` header
47            // <https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Server>
48            .with_header("Server", server_info())
49            .with_header(
50                format!("{CUSTOM_HEADER_PREFIX}.Cardano-Network"),
51                Settings::cardano_network().to_string(),
52            )
53            .into_response())
54    }
55}
56
57/// Returns a cat-gateway server info in the following format,
58/// based on the `User-Agent` <https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/User-Agent>
59/// ```
60/// cat-gateway/<service-id> commit:<git_commit>,branch:<git_branch>,tags:<git_tag1>,<git_tag2>
61/// ```
62fn server_info() -> String {
63    let cat_gateway_info = build_info();
64    let mut server_info = format!("cat-gateway/{}", settings::Settings::service_id());
65    if let Some(vc) = &cat_gateway_info.version_control {
66        if let Some(git) = vc.git() {
67            let _ = write!(&mut server_info, " commit:{}", git.commit_short_id);
68            if let Some(branch) = &git.branch {
69                let _ = write!(&mut server_info, ",branch:{branch}");
70            }
71            if !git.tags.is_empty() {
72                let _ = write!(&mut server_info, ",tags:{}", git.tags.join(","));
73            }
74        }
75    }
76    server_info
77}
78
79#[cfg(test)]
80mod tests {
81    use super::*;
82
83    #[test]
84    fn server_info_test() {
85        println!("{}", server_info());
86    }
87}