1use std::{fmt::Display, net::IpAddr};
2
3use serde::{Deserialize, Serialize};
4
5use super::plugin::PluginInstanceId;
6
7#[derive(Debug, Serialize, Deserialize, Clone)]
12#[cfg_attr(feature = "typegen", derive(ts_rs::TS), ts(export))]
13#[serde(default)]
14pub struct SgGateway<P = PluginInstanceId> {
16 pub name: String,
17 pub parameters: SgParameters,
19 #[serde(skip_serializing_if = "Vec::is_empty")]
20 pub listeners: Vec<SgListener>,
22 #[serde(skip_serializing_if = "Vec::is_empty")]
23 pub plugins: Vec<P>,
25}
26
27impl<P> Default for SgGateway<P> {
28 fn default() -> Self {
29 Self {
30 name: Default::default(),
31 parameters: Default::default(),
32 listeners: Default::default(),
33 plugins: Default::default(),
34 }
35 }
36}
37
38impl<P> SgGateway<P> {
39 pub fn map_plugins<F, T>(self, f: F) -> SgGateway<T>
40 where
41 F: FnMut(P) -> T,
42 {
43 SgGateway {
44 name: self.name,
45 parameters: self.parameters,
46 listeners: self.listeners,
47 plugins: self.plugins.into_iter().map(f).collect(),
48 }
49 }
50}
51
52#[derive(Default, Debug, Serialize, Deserialize, Clone)]
54#[cfg_attr(feature = "typegen", derive(ts_rs::TS), ts(export))]
55#[serde(default)]
56pub struct SgParameters {
57 #[serde(skip_serializing_if = "Option::is_none")]
58 pub redis_url: Option<String>,
60 #[serde(skip_serializing_if = "Option::is_none")]
61 pub log_level: Option<String>,
63 #[serde(skip_serializing_if = "Option::is_none")]
64 pub lang: Option<String>,
66 #[serde(skip_serializing_if = "Option::is_none")]
67 pub ignore_tls_verification: Option<bool>,
69 #[serde(skip_serializing_if = "Option::is_none")]
70 pub enable_x_request_id: Option<bool>,
72}
73
74#[derive(Default, Debug, Serialize, Deserialize, Clone)]
76#[cfg_attr(feature = "typegen", derive(ts_rs::TS), ts(export))]
77#[serde(default)]
78pub struct SgListener {
79 pub name: String,
81 #[serde(skip_serializing_if = "Option::is_none")]
82 pub ip: Option<IpAddr>,
84 pub port: u16,
86 pub protocol: SgProtocolConfig,
88 #[serde(skip_serializing_if = "Option::is_none")]
89 pub hostname: Option<String>,
91}
92
93#[non_exhaustive]
94#[cfg_attr(feature = "typegen", derive(ts_rs::TS), ts(export))]
96#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Default)]
97#[serde(rename_all = "lowercase")]
98pub enum SgBackendProtocol {
99 #[default]
102 Http,
103 Https,
105}
106
107impl Display for SgBackendProtocol {
108 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109 match self {
110 SgBackendProtocol::Http => write!(f, "http"),
111 SgBackendProtocol::Https { .. } => write!(f, "https"),
112 }
113 }
114}
115
116#[non_exhaustive]
117#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Default)]
119#[serde(rename_all = "lowercase", tag = "type")]
120#[cfg_attr(feature = "typegen", derive(ts_rs::TS), ts(export))]
121pub enum SgProtocolConfig {
122 #[default]
125 Http,
126 Https {
128 tls: SgTlsConfig,
131 },
132}
133
134impl Display for SgProtocolConfig {
135 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
136 match self {
137 SgProtocolConfig::Http => write!(f, "http"),
138 SgProtocolConfig::Https { .. } => write!(f, "https"),
139 }
140 }
141}
142
143#[derive(Debug, Serialize, PartialEq, Eq, Deserialize, Clone)]
145#[cfg_attr(feature = "typegen", derive(ts_rs::TS), ts(export))]
146pub struct SgTlsConfig {
147 pub mode: SgTlsMode,
148 pub key: String,
149 pub cert: String,
150 pub http2: Option<bool>,
151}
152
153#[derive(Debug, Serialize, PartialEq, Deserialize, Clone, Default, Eq, Copy)]
154#[cfg_attr(feature = "typegen", derive(ts_rs::TS), ts(export))]
155pub enum SgTlsMode {
156 Terminate,
157 #[default]
158 Passthrough,
159}
160
161impl From<SgTlsMode> for String {
162 fn from(value: SgTlsMode) -> Self {
163 match value {
164 SgTlsMode::Terminate => "Terminate".to_string(),
165 SgTlsMode::Passthrough => "Passthrough".to_string(),
166 }
167 }
168}
169
170impl From<String> for SgTlsMode {
171 fn from(value: String) -> Self {
172 match value.to_lowercase().as_str() {
173 "terminate" => SgTlsMode::Terminate,
174 "passthrough" => SgTlsMode::Passthrough,
175 _ => SgTlsMode::Passthrough,
176 }
177 }
178}
179
180impl From<Option<String>> for SgTlsMode {
181 fn from(value: Option<String>) -> Self {
182 SgTlsMode::from(value.unwrap_or_default())
183 }
184}
185
186impl SgTlsMode {
187 pub fn to_pascal_case(&self) -> &'static str {
188 match self {
189 SgTlsMode::Terminate => "Terminate",
190 SgTlsMode::Passthrough => "Passthrough",
191 }
192 }
193}