spacegate_kernel/service/http_route/
builder.rs

1use std::{fmt::Debug, path::PathBuf, time::Duration};
2
3use hyper::Version;
4
5use crate::BoxLayer;
6
7use super::{match_request::HttpRouteMatch, Backend, BalancePolicyEnum, HttpBackend, HttpRoute, HttpRouteRule};
8
9#[derive(Debug)]
10pub struct HttpRouteBuilder {
11    pub name: String,
12    pub hostnames: Vec<String>,
13    pub rules: Vec<HttpRouteRule>,
14    pub plugins: Vec<BoxLayer>,
15    pub priority: Option<i16>,
16    pub extensions: hyper::http::Extensions,
17}
18
19impl Default for HttpRouteBuilder {
20    fn default() -> Self {
21        Self::new()
22    }
23}
24
25impl HttpRouteBuilder {
26    pub fn new() -> Self {
27        Self {
28            name: Default::default(),
29            hostnames: Vec::new(),
30            rules: Vec::new(),
31            plugins: Vec::new(),
32            priority: None,
33            extensions: Default::default(),
34        }
35    }
36    pub fn name(mut self, name: impl Into<String>) -> Self {
37        self.name = name.into();
38        self
39    }
40    pub fn hostnames(mut self, hostnames: impl IntoIterator<Item = String>) -> Self {
41        self.hostnames = hostnames.into_iter().collect();
42        self
43    }
44    pub fn rule(mut self, rule: HttpRouteRule) -> Self {
45        self.rules.push(rule);
46        self
47    }
48    pub fn rules(mut self, rules: impl IntoIterator<Item = HttpRouteRule>) -> Self {
49        self.rules.extend(rules);
50        self
51    }
52    pub fn plugin(mut self, plugin: BoxLayer) -> Self {
53        self.plugins.push(plugin);
54        self
55    }
56    pub fn plugins(mut self, plugins: impl IntoIterator<Item = BoxLayer>) -> Self {
57        self.plugins.extend(plugins);
58        self
59    }
60    pub fn priority(mut self, priority: i16) -> Self {
61        self.priority = Some(priority);
62        self
63    }
64    pub fn ext(mut self, extensions: hyper::http::Extensions) -> Self {
65        self.extensions = extensions;
66        self
67    }
68    pub fn build(mut self) -> HttpRoute {
69        if self.hostnames.iter().any(|host| host == "*") {
70            self.hostnames = vec!["*".to_string()]
71        }
72        HttpRoute {
73            plugins: self.plugins,
74            hostnames: self.hostnames,
75            rules: self.rules,
76            priority: self.priority.unwrap_or(1),
77            name: self.name,
78            ext: self.extensions,
79        }
80    }
81}
82
83#[derive(Debug)]
84pub struct HttpRouteRuleBuilder {
85    r#match: Option<Vec<HttpRouteMatch>>,
86    pub plugins: Vec<BoxLayer>,
87    timeouts: Option<Duration>,
88    backends: Vec<HttpBackend>,
89    pub extensions: hyper::http::Extensions,
90    pub balance_policy: BalancePolicyEnum,
91}
92impl Default for HttpRouteRuleBuilder {
93    fn default() -> Self {
94        Self::new()
95    }
96}
97
98impl HttpRouteRuleBuilder {
99    pub fn new() -> Self {
100        Self {
101            r#match: None,
102            plugins: Vec::new(),
103            timeouts: None,
104            backends: Vec::new(),
105            extensions: Default::default(),
106            balance_policy: BalancePolicyEnum::default(),
107        }
108    }
109    pub fn match_item(mut self, item: impl Into<HttpRouteMatch>) -> Self {
110        match self.r#match {
111            Some(ref mut matches) => matches.push(item.into()),
112            None => self.r#match = Some(vec![item.into()]),
113        }
114        self
115    }
116    pub fn matches(mut self, matches: impl IntoIterator<Item = HttpRouteMatch>) -> Self {
117        self.r#match = Some(matches.into_iter().collect());
118        self
119    }
120    pub fn match_all(mut self) -> Self {
121        self.r#match = None;
122        self
123    }
124    pub fn plugin(mut self, plugin: BoxLayer) -> Self {
125        self.plugins.push(plugin);
126        self
127    }
128    pub fn plugins(mut self, plugins: impl IntoIterator<Item = BoxLayer>) -> Self {
129        self.plugins.extend(plugins);
130        self
131    }
132    pub fn timeout(mut self, timeout: Duration) -> Self {
133        self.timeouts = Some(timeout);
134        self
135    }
136    pub fn backend(mut self, backend: HttpBackend) -> Self {
137        self.backends.push(backend);
138        self
139    }
140    pub fn backends(mut self, backend: impl IntoIterator<Item = HttpBackend>) -> Self {
141        self.backends.extend(backend);
142        self
143    }
144    pub fn balance_policy(mut self, policy: BalancePolicyEnum) -> Self {
145        self.balance_policy = policy;
146        self
147    }
148    pub fn build(self) -> HttpRouteRule {
149        HttpRouteRule {
150            r#match: self.r#match,
151            plugins: self.plugins,
152            timeouts: self.timeouts,
153            backends: self.backends,
154            ext: self.extensions,
155            balance_policy: self.balance_policy,
156        }
157    }
158    pub fn ext(mut self, extension: hyper::http::Extensions) -> Self {
159        self.extensions = extension;
160        self
161    }
162}
163pub trait BackendKindBuilder: Default + Debug {
164    fn build(self) -> Backend;
165}
166#[derive(Debug)]
167pub struct HttpBackendBuilder<B: BackendKindBuilder = HttpBackendKindBuilder> {
168    backend: B,
169    pub plugins: Vec<BoxLayer>,
170    timeout: Option<Duration>,
171    weight: u16,
172    pub extensions: hyper::http::Extensions,
173}
174
175#[derive(Debug, Default, Clone)]
176pub struct HttpBackendKindBuilder {
177    pub host: Option<String>,
178    pub port: Option<u16>,
179    pub schema: Option<String>,
180    pub version: Option<Version>,
181}
182
183impl BackendKindBuilder for HttpBackendKindBuilder {
184    fn build(self) -> Backend {
185        Backend::Http {
186            host: self.host,
187            port: self.port,
188            schema: self.schema,
189            version: self.version,
190        }
191    }
192}
193#[derive(Debug, Default, Clone)]
194
195pub struct FileBackendKindBuilder {
196    path: PathBuf,
197}
198
199impl BackendKindBuilder for FileBackendKindBuilder {
200    fn build(self) -> Backend {
201        Backend::File { path: self.path }
202    }
203}
204
205impl<B: BackendKindBuilder> Default for HttpBackendBuilder<B> {
206    fn default() -> Self {
207        Self {
208            backend: B::default(),
209            plugins: Vec::new(),
210            timeout: None,
211            weight: 1,
212            extensions: Default::default(),
213        }
214    }
215}
216
217impl HttpBackendBuilder<FileBackendKindBuilder> {
218    pub fn path(mut self, path: impl Into<PathBuf>) -> Self {
219        self.backend = FileBackendKindBuilder { path: path.into() };
220        self
221    }
222}
223
224impl HttpBackendBuilder<HttpBackendKindBuilder> {
225    pub fn host(mut self, host: impl Into<String>) -> Self {
226        self.backend = HttpBackendKindBuilder {
227            host: Some(host.into()),
228            ..self.backend
229        };
230        self
231    }
232    pub fn port(mut self, port: u16) -> Self {
233        self.backend = HttpBackendKindBuilder { port: Some(port), ..self.backend };
234        self
235    }
236    pub fn schema(mut self, schema: impl Into<String>) -> Self {
237        self.backend = HttpBackendKindBuilder {
238            schema: Some(schema.into()),
239            ..self.backend
240        };
241        self
242    }
243    pub fn version(mut self, version: Version) -> Self {
244        self.backend = HttpBackendKindBuilder {
245            version: Some(version),
246            ..self.backend
247        };
248        self
249    }
250}
251
252impl<B: BackendKindBuilder> HttpBackendBuilder<B> {
253    pub fn new() -> Self {
254        Self::default()
255    }
256    pub fn plugin(mut self, plugin: BoxLayer) -> Self {
257        self.plugins.push(plugin);
258        self
259    }
260    pub fn plugins(mut self, plugins: impl IntoIterator<Item = BoxLayer>) -> Self {
261        self.plugins.extend(plugins);
262        self
263    }
264    pub fn timeout(mut self, timeout: Duration) -> Self {
265        self.timeout = Some(timeout);
266        self
267    }
268    pub fn weight(mut self, weight: u16) -> Self {
269        self.weight = weight;
270        self
271    }
272    pub fn http(self) -> HttpBackendBuilder<HttpBackendKindBuilder> {
273        HttpBackendBuilder {
274            backend: HttpBackendKindBuilder::default(),
275            plugins: self.plugins,
276            timeout: self.timeout,
277            weight: self.weight,
278            extensions: self.extensions,
279        }
280    }
281    pub fn file(self) -> HttpBackendBuilder<FileBackendKindBuilder> {
282        HttpBackendBuilder {
283            backend: FileBackendKindBuilder::default(),
284            plugins: self.plugins,
285            timeout: self.timeout,
286            weight: self.weight,
287            extensions: self.extensions,
288        }
289    }
290    pub fn ext(mut self, extension: hyper::http::Extensions) -> Self {
291        self.extensions = extension;
292        self
293    }
294    pub fn build(self) -> HttpBackend {
295        HttpBackend {
296            backend: self.backend.build(),
297            plugins: self.plugins,
298            timeout: self.timeout,
299            weight: self.weight,
300            ext: self.extensions,
301        }
302    }
303}