Skip to main content

runx_runtime/http/
types.rs

1use std::fmt;
2
3use super::RuntimeHttpError;
4
5#[derive(Clone, Copy, Debug, Eq, PartialEq)]
6pub enum HttpMethod {
7    Get,
8    Post,
9    Put,
10    Patch,
11    Delete,
12}
13
14impl HttpMethod {
15    pub fn as_str(self) -> &'static str {
16        match self {
17            Self::Get => "GET",
18            Self::Post => "POST",
19            Self::Put => "PUT",
20            Self::Patch => "PATCH",
21            Self::Delete => "DELETE",
22        }
23    }
24}
25
26#[derive(Clone, Eq, PartialEq)]
27pub struct RuntimeHttpHeader {
28    pub name: String,
29    pub value: String,
30}
31
32impl RuntimeHttpHeader {
33    pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
34        Self {
35            name: name.into(),
36            value: value.into(),
37        }
38    }
39}
40
41impl fmt::Debug for RuntimeHttpHeader {
42    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
43        formatter
44            .debug_struct("RuntimeHttpHeader")
45            .field("name", &self.name)
46            .field(
47                "value",
48                &if sensitive_header_name(&self.name) {
49                    "[redacted]"
50                } else {
51                    self.value.as_str()
52                },
53            )
54            .finish()
55    }
56}
57
58#[derive(Clone, Eq, PartialEq)]
59pub struct RuntimeHttpRequest {
60    pub method: HttpMethod,
61    pub url: String,
62    pub headers: Vec<RuntimeHttpHeader>,
63    pub body: Option<String>,
64}
65
66impl fmt::Debug for RuntimeHttpRequest {
67    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
68        formatter
69            .debug_struct("RuntimeHttpRequest")
70            .field("method", &self.method)
71            .field("url", &self.url)
72            .field("headers", &self.headers)
73            .field(
74                "body",
75                &self.body.as_ref().map(|_| "[redacted body present]"),
76            )
77            .finish()
78    }
79}
80
81#[derive(Clone, Eq, PartialEq)]
82pub struct RuntimeHttpResponse {
83    pub status: u16,
84    pub body: String,
85}
86
87impl fmt::Debug for RuntimeHttpResponse {
88    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
89        formatter
90            .debug_struct("RuntimeHttpResponse")
91            .field("status", &self.status)
92            .field("body", &format_args!("{} bytes", self.body.len()))
93            .finish()
94    }
95}
96
97pub trait RuntimeHttpTransport {
98    fn send(&self, request: RuntimeHttpRequest) -> Result<RuntimeHttpResponse, RuntimeHttpError>;
99}
100
101#[derive(Clone, Debug)]
102pub struct ReqwestHttpTransport {
103    #[cfg(feature = "async-http")]
104    pub(super) client: reqwest::Client,
105    #[cfg(feature = "async-http")]
106    pub(super) allow_private_networks: bool,
107}
108
109pub(super) fn sensitive_header_name(name: &str) -> bool {
110    let normalized = name.to_ascii_lowercase();
111    normalized == "authorization"
112        || normalized == "proxy-authorization"
113        || normalized.contains("token")
114        || normalized.contains("secret")
115        || normalized.contains("api-key")
116}