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(&self, ep: E) -> Self::Output {
23        CatGatewayInfoImpl { ep }
24    }
25}
26
27/// The new endpoint type generated by the `CatGatewayInfo`.
28pub(crate) struct CatGatewayInfoImpl<E> {
29    /// Endpoint wrapped by the middleware.
30    ep: E,
31}
32
33impl<E: Endpoint> Endpoint for CatGatewayInfoImpl<E> {
34    type Output = Response;
35
36    async fn call(&self, req: Request) -> Result<Self::Output> {
37        let resp = self.ep.call(req).await?.into_response();
38
39        Ok(resp
40            // using a `Server` header
41            // <https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Server>
42            .with_header("Server", server_info())
43            .with_header(
44                format!("{CUSTOM_HEADER_PREFIX}.Cardano-Network"),
45                Settings::cardano_network().to_string(),
46            )
47            .into_response())
48    }
49}
50
51/// Returns a cat-gateway server info in the following format,
52/// based on the `User-Agent` <https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/User-Agent>
53/// ```
54/// cat-gateway/<service-id> commit:<git_commit>,branch:<git_branch>,tags:<git_tag1>,<git_tag2>
55/// ```
56fn server_info() -> String {
57    let cat_gateway_info = build_info();
58    let mut server_info = format!("cat-gateway/{}", settings::Settings::service_id());
59    if let Some(vc) = &cat_gateway_info.version_control {
60        if let Some(git) = vc.git() {
61            let _ = write!(&mut server_info, " commit:{}", git.commit_short_id);
62            if let Some(branch) = &git.branch {
63                let _ = write!(&mut server_info, ",branch:{branch}");
64            }
65            if !git.tags.is_empty() {
66                let _ = write!(&mut server_info, ",tags:{}", git.tags.join(","));
67            }
68        }
69    }
70    server_info
71}
72
73#[cfg(test)]
74mod tests {
75    use super::*;
76
77    #[test]
78    #[ignore]
79    fn server_info_test() {
80        println!("{}", server_info());
81    }
82}