1use crate::{error::Error, subject_name::SubjectName};
2use regex::Regex;
3use serde::{Deserialize, Serialize};
4use std::fmt;
5use std::str::FromStr;
6
7#[derive(Debug, Clone)]
8pub enum VirtualHost {
9 SubjectName(SubjectName),
10 Regex(Regex),
11}
12
13impl VirtualHost {
14 pub fn test(&self, name: &str) -> bool {
15 match self {
16 VirtualHost::SubjectName(n) => n.test(name),
17 VirtualHost::Regex(r) => r.is_match(name),
18 }
19 }
20}
21
22impl PartialEq for VirtualHost {
23 fn eq(&self, other: &Self) -> bool {
24 match (self, other) {
25 (VirtualHost::SubjectName(a), VirtualHost::SubjectName(b)) => a == b,
26 (VirtualHost::Regex(a), VirtualHost::Regex(b)) => a.as_str() == b.as_str(),
27 _ => false,
28 }
29 }
30}
31
32impl Eq for VirtualHost {}
33
34impl fmt::Display for VirtualHost {
35 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36 match self {
37 VirtualHost::SubjectName(name) => write!(f, "{}", name),
38 VirtualHost::Regex(r) => write!(f, "{}", r),
39 }
40 }
41}
42
43impl FromStr for VirtualHost {
44 type Err = Error;
45
46 fn from_str(s: &str) -> Result<Self, Self::Err> {
47 if let Ok(n) = SubjectName::from_str(s) {
48 Ok(VirtualHost::SubjectName(n))
49 } else if let Ok(r) = Regex::new(s) {
50 Ok(VirtualHost::Regex(r))
51 } else {
52 Err(Error::InvalidVirtualHost { host: s.into() })
53 }
54 }
55}
56
57impl Serialize for VirtualHost {
58 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
59 where
60 S: serde::Serializer,
61 {
62 serializer.serialize_str(&self.to_string())
63 }
64}
65
66impl<'de> Deserialize<'de> for VirtualHost {
67 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
68 where
69 D: serde::Deserializer<'de>,
70 {
71 let s = String::deserialize(deserializer)?;
72 Self::from_str(&s).map_err(serde::de::Error::custom)
73 }
74}
75
76#[cfg(test)]
77mod test {
78 #[test]
79 fn test_virtual_host() {
80 use super::VirtualHost;
81 use std::str::FromStr;
82
83 let host = VirtualHost::from_str("localhost").unwrap();
84 assert_eq!(host.to_string(), "localhost");
85 assert!(host.test("localhost"));
86 assert!(!host.test("example.com"));
87
88 let host = VirtualHost::from_str("^.*\\.example\\.com$").unwrap();
89 assert_eq!(host.to_string(), "^.*\\.example\\.com$");
90 assert!(!host.test("localhost"));
91 assert!(host.test("www.example.com"));
92
93 let host = VirtualHost::from_str("^([a-z]+\\.)+my\\.vow$").unwrap();
94 assert_eq!(host.to_string(), "^([a-z]+\\.)+my\\.vow$");
95 assert!(!host.test("localhost"));
96 assert!(host.test("sphinx.of.black.quartz.judge.my.vow"));
97 }
98}