use std::sync::Arc;
use std::io::{Error, Result, ErrorKind};
use pi_hash::XHashMap;
use pi_atom::Atom;
use tcp::Socket;
use crate::{service::{HttpService, ServiceFactory},
gateway::{GatewayContext, HttpGateway},
route::{RouterTab, HttpRoute},
middleware::Middleware};
pub trait VirtualHostPool<S: Socket>: Clone + Send + Sync + 'static {
type Host: ServiceFactory<S>;
fn size(&self) -> usize;
fn get(&self, name: &str) -> Option<&Self::Host>;
fn add(&mut self, name: &str, host: Self::Host) -> Result<()>;
fn add_default(&mut self, host: Self::Host) -> Result<()>;
}
pub struct VirtualHostTab<S: Socket, H: Middleware<S, GatewayContext>>(Arc<XHashMap<Atom, VirtualHost<S, H>>>);
unsafe impl<S: Socket, H: Middleware<S, GatewayContext>> Send for VirtualHostTab<S, H> {}
unsafe impl<S: Socket, H: Middleware<S, GatewayContext>> Sync for VirtualHostTab<S, H> {}
impl<S: Socket, H: Middleware<S, GatewayContext>> Clone for VirtualHostTab<S, H> {
fn clone(&self) -> Self {
VirtualHostTab(self.0.clone())
}
}
impl<S: Socket, H: Middleware<S, GatewayContext>> VirtualHostPool<S> for VirtualHostTab<S, H> {
type Host = VirtualHost<S, H>;
fn size(&self) -> usize {
self.0.len()
}
fn get(&self, name: &str) -> Option<&Self::Host> {
let host: Vec<&str> = name.split(":").collect();
if let Some(host) = self.0.get(&Atom::from(host[0])) {
Some(host)
} else {
self.0.get(&Atom::from(""))
}
}
fn add(&mut self, name: &str, host: Self::Host) -> Result<()> {
if let Some(tab) = Arc::get_mut(&mut self.0) {
tab.insert(Atom::from(name), host);
return Ok(());
}
Err(Error::new(ErrorKind::Other,
format!("Add virtual host error, host: {:?}, reason: not writable",
name)))
}
fn add_default(&mut self, host: Self::Host) -> Result<()> {
self.add("", host)
}
}
impl<S: Socket, H: Middleware<S, GatewayContext>> VirtualHostTab<S, H> {
pub fn new() -> Self {
VirtualHostTab(Arc::new(XHashMap::default()))
}
}
pub struct VirtualHost<S: Socket, H: Middleware<S, GatewayContext>>(Arc<RouterTab<S, GatewayContext, H>>);
unsafe impl<S: Socket, H: Middleware<S, GatewayContext>> Send for VirtualHost<S, H> {}
unsafe impl<S: Socket, H: Middleware<S, GatewayContext>> Sync for VirtualHost<S, H> {}
impl<S: Socket, H: Middleware<S, GatewayContext>> Clone for VirtualHost<S, H> {
fn clone(&self) -> Self {
VirtualHost(self.0.clone())
}
}
impl<S: Socket, H: Middleware<S, GatewayContext>> ServiceFactory<S> for VirtualHost<S, H> {
type Service = HttpGateway<S, H>;
fn new_service(&self) -> Self::Service {
HttpGateway::with(self.0.clone())
}
}
impl<S: Socket, H: Middleware<S, GatewayContext>> VirtualHost<S, H> {
pub fn with(route: HttpRoute<S, GatewayContext, H>) -> Self {
VirtualHost(Arc::new(route.into()))
}
}