use crate::types::{AccessLog, ErrorLog, ListenDirective, Location};
use std::path::PathBuf;
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Server {
pub server_names: Vec<String>,
pub listen: Vec<ListenDirective>,
pub root: Option<PathBuf>,
pub locations: Vec<Location>,
pub access_logs: Vec<AccessLog>,
pub error_logs: Vec<ErrorLog>,
pub index: Vec<String>,
}
impl Default for Server {
fn default() -> Self {
Self::new()
}
}
impl Server {
#[must_use]
pub fn new() -> Self {
Self {
server_names: Vec::new(),
listen: Vec::new(),
root: None,
locations: Vec::new(),
access_logs: Vec::new(),
error_logs: Vec::new(),
index: Vec::new(),
}
}
#[must_use]
pub fn with_server_name(mut self, name: impl Into<String>) -> Self {
self.server_names.push(name.into());
self
}
#[must_use]
pub fn with_listen(mut self, listen: ListenDirective) -> Self {
self.listen.push(listen);
self
}
#[must_use]
pub fn with_root(mut self, root: impl Into<PathBuf>) -> Self {
self.root = Some(root.into());
self
}
#[must_use]
pub fn has_ssl(&self) -> bool {
self.listen.iter().any(|l| l.ssl)
}
#[must_use]
pub fn is_default_server(&self) -> bool {
self.listen.iter().any(|l| l.default_server)
}
#[must_use]
pub fn primary_name(&self) -> Option<&str> {
self.server_names.first().map(String::as_str)
}
#[must_use]
pub fn with_index(mut self, index: impl Into<String>) -> Self {
self.index.push(index.into());
self
}
#[must_use]
pub fn with_location(mut self, location: Location) -> Self {
self.locations.push(location);
self
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::types::LocationModifier;
#[test]
fn test_server_new() {
let server = Server::new();
assert!(server.server_names.is_empty());
assert!(server.listen.is_empty());
assert!(server.root.is_none());
assert!(server.locations.is_empty());
assert!(server.access_logs.is_empty());
assert!(server.error_logs.is_empty());
assert!(server.index.is_empty());
}
#[test]
fn test_server_default() {
let server = Server::default();
assert!(server.server_names.is_empty());
assert!(server.listen.is_empty());
}
#[test]
fn test_with_server_name() {
let server = Server::new()
.with_server_name("example.com")
.with_server_name("www.example.com");
assert_eq!(server.server_names.len(), 2);
assert_eq!(server.server_names[0], "example.com");
assert_eq!(server.server_names[1], "www.example.com");
}
#[test]
fn test_with_listen() {
let listen = ListenDirective::new("0.0.0.0", 80);
let server = Server::new().with_listen(listen.clone());
assert_eq!(server.listen.len(), 1);
assert_eq!(server.listen[0].port, 80);
assert_eq!(server.listen[0].address, "0.0.0.0");
}
#[test]
fn test_with_root() {
let server = Server::new().with_root("/var/www/html");
assert!(server.root.is_some());
assert_eq!(server.root.unwrap(), PathBuf::from("/var/www/html"));
}
#[test]
fn test_with_index() {
let server = Server::new()
.with_index("index.html")
.with_index("index.php");
assert_eq!(server.index.len(), 2);
assert_eq!(server.index[0], "index.html");
assert_eq!(server.index[1], "index.php");
}
#[test]
fn test_with_location() {
let location = Location::new("/", LocationModifier::None);
let server = Server::new().with_location(location);
assert_eq!(server.locations.len(), 1);
assert_eq!(server.locations[0].path, "/");
}
#[test]
fn test_has_ssl_true() {
let mut listen_ssl = ListenDirective::new("0.0.0.0", 443);
listen_ssl.ssl = true;
let server = Server::new().with_listen(listen_ssl);
assert!(server.has_ssl());
}
#[test]
fn test_has_ssl_false() {
let listen = ListenDirective::new("0.0.0.0", 80);
let server = Server::new().with_listen(listen);
assert!(!server.has_ssl());
}
#[test]
fn test_has_ssl_mixed() {
let listen_http = ListenDirective::new("0.0.0.0", 80);
let mut listen_https = ListenDirective::new("0.0.0.0", 443);
listen_https.ssl = true;
let server = Server::new()
.with_listen(listen_http)
.with_listen(listen_https);
assert!(server.has_ssl());
}
#[test]
fn test_is_default_server_true() {
let mut listen = ListenDirective::new("0.0.0.0", 80);
listen.default_server = true;
let server = Server::new().with_listen(listen);
assert!(server.is_default_server());
}
#[test]
fn test_is_default_server_false() {
let listen = ListenDirective::new("0.0.0.0", 80);
let server = Server::new().with_listen(listen);
assert!(!server.is_default_server());
}
#[test]
fn test_primary_name_some() {
let server = Server::new()
.with_server_name("example.com")
.with_server_name("www.example.com");
assert_eq!(server.primary_name(), Some("example.com"));
}
#[test]
fn test_primary_name_none() {
let server = Server::new();
assert_eq!(server.primary_name(), None);
}
#[test]
fn test_builder_pattern_complete() {
let mut listen = ListenDirective::new("0.0.0.0", 443);
listen.ssl = true;
let location = Location::new("/api", LocationModifier::None);
let server = Server::new()
.with_server_name("example.com")
.with_listen(listen)
.with_root("/var/www")
.with_index("index.html")
.with_location(location);
assert_eq!(server.server_names.len(), 1);
assert_eq!(server.listen.len(), 1);
assert!(server.root.is_some());
assert_eq!(server.index.len(), 1);
assert_eq!(server.locations.len(), 1);
assert!(server.has_ssl());
}
}