⎇ 3f8a3ea4b6d3de529e42ae418d486bc81cca308e
crates/modules/matilda/matilda-core/src/vhost.rs
Historia
Quién tocó qué
crudo
feat(matilda): administración de servidores — core + config + plan
1//! `VHost` — un host virtual de proxy inverso.
2
3use serde::{Deserialize, Serialize};
4
5/// El destino al que un `VHost` reenvía el tráfico.
6#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
7pub enum Upstream {
8 /// Una dirección `host:puerto` literal.
9 Address(String),
10 /// Un contenedor del inventario, por nombre y puerto interno.
11 Container { name: String, port: u16 },
12}
13
14/// Un host virtual: un dominio que se reenvía a un upstream. Clave
15/// única: `domain`.
16#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
17pub struct VHost {
18 pub domain: String,
19 pub upstream: Upstream,
20 /// Si se sirve sobre HTTPS.
21 pub tls: bool,
22 /// Dominios alternativos que resuelven al mismo upstream.
23 pub aliases: Vec<String>,
24}
25
26impl VHost {
27 /// VHost que apunta a una dirección literal.
28 pub fn to_address(domain: impl Into<String>, address: impl Into<String>) -> Self {
29 Self {
30 domain: domain.into(),
31 upstream: Upstream::Address(address.into()),
32 tls: false,
33 aliases: Vec::new(),
34 }
35 }
36
37 /// VHost que apunta a un contenedor del inventario.
38 pub fn to_container(
39 domain: impl Into<String>,
40 container: impl Into<String>,
41 port: u16,
42 ) -> Self {
43 Self {
44 domain: domain.into(),
45 upstream: Upstream::Container { name: container.into(), port },
46 tls: false,
47 aliases: Vec::new(),
48 }
49 }
50
51 /// Activa TLS (encadenable).
52 pub fn with_tls(mut self) -> Self {
53 self.tls = true;
54 self
55 }
56
57 /// Añade un alias de dominio (encadenable).
58 pub fn with_alias(mut self, alias: impl Into<String>) -> Self {
59 self.aliases.push(alias.into());
60 self
61 }
62
63 /// Nombre del contenedor del que depende, si el upstream es uno.
64 pub fn depends_on_container(&self) -> Option<&str> {
65 match &self.upstream {
66 Upstream::Container { name, .. } => Some(name),
67 Upstream::Address(_) => None,
68 }
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 #[test]
77 fn container_upstream_reports_its_dependency() {
78 let v = VHost::to_container("app.example.com", "web", 8080).with_tls();
79 assert_eq!(v.depends_on_container(), Some("web"));
80 assert!(v.tls);
81 }
82
83 #[test]
84 fn address_upstream_has_no_container_dependency() {
85 let v = VHost::to_address("static.example.com", "10.0.0.9:80");
86 assert_eq!(v.depends_on_container(), None);
87 }
88}