use std::collections::HashMap;
#[cfg(feature = "debugging")]
use tracing::error;
#[cfg(feature = "auto_encode_response")]
use crate::server::encoding::{EncodingConfigurations};
pub (crate) const EACH_REQUEST_BODY_READING_BUFFER:usize = 4096*4;
pub (crate) const READING_BUF_LEN:usize = 4096*4;
pub (crate) const WRITING_BUF_LEN:usize = 4096*8;
pub (crate) const WRITING_FILES_BUF_LEN:usize = 1024*20;
pub (crate) static mut ___ALL_ROUTES:Option<HashMap<String,String>> = None;
#[allow(static_mut_refs)]
#[doc(hidden)]
pub fn get_route(key:&str,mut params:Option<HashMap<&str,&str>>)->Option<String>{
unsafe {
match ___ALL_ROUTES.as_ref() {
None => {}
Some(___a) => {
if let Some(route) = ___a.get(key) {
let mut route = route.to_string();
loop {
if let Some(f_index) = route.find("{") {
if let Some(s_index) = (&route[f_index..]).find("}") {
let param = &route[f_index+1..s_index];
match params {
None => {
#[cfg(feature = "debugging")]
error!("you should provide {param} with your given route {key}");
return None
}
Some(ref mut all_params) => {
if let Some(k) = all_params.get(param) {
let param = param.to_string();
route = route.replace(&format!("{}{}{}","{",param,"}"),*k);
all_params.remove(param.as_str());
continue;
} else {
return None;
}
}
}
} else {break;}
} else {break;}
}
match params {
None => {}
Some( p) => {
for (index,(key,value)) in p.iter().enumerate() {
if index==0 {route.push_str("?");}
else { route.push_str("&"); }
route.push_str(&format!("{key}="));
route.push_str(value);
}
}
}
return Some(route)
}
}
}
}
None
}
#[allow(static_mut_refs)]
pub (crate) fn push_named_route(name:String,route:String){
unsafe {
match ___ALL_ROUTES.as_mut() {
None => {
let mut map = HashMap::new();
map.insert(name,route);
___ALL_ROUTES = Some(map);
}
Some(map ) => {
map.insert(name,route);
}
}
}
}
pub enum RestrictionRule {
OnlyAllowedIps(Vec<String>),
BlacklistIps(Vec<String>),
}
pub struct ServerConfigurations {
pub addresses:Vec<(String,u16)>,
pub worker_threads_count:usize,
pub restricted_ips:Option<RestrictionRule>,
#[cfg(feature = "auto_encode_response")]
pub (crate) responding_encoding_configurations:EncodingConfigurations,
#[cfg(all(feature = "support_tls",not(feature="use_io_uring")))]
pub tls_certificate:Option<TLSCertificate>,
pub core_affinity:bool,
#[cfg(all(feature = "support_tls",not(feature="use_io_uring")))]
pub tls_ports:Vec<u16>,
pub listeners_count:usize,
pub max_buffer_size_for_cache:usize,
pub default_read_buffer_size:usize,
pub default_write_buffer_size:usize,
pub default_body_buffer_size:usize,
pub max_cached_buffers_count:usize,
pub backlog:u32,
pub max_request_size:usize,
}
#[cfg(all(feature = "support_tls",not(feature="use_io_uring")))]
pub struct TLSCertificate {
pub tls_cert:String,
pub tls_key:String,
pub tls_ca_bundle:Option<String>,
}
impl ServerConfigurations {
pub fn default()->Self {
let worker_threads = std::thread::available_parallelism()
.map(|n| n.get())
.unwrap_or(4);
ServerConfigurations{
addresses:vec![("0.0.0.0".to_string(),80),],
#[cfg(all(feature = "support_tls",not(feature="use_io_uring")))]
tls_certificate:None,
core_affinity:false,
restricted_ips:None,
#[cfg(feature = "auto_encode_response")]
responding_encoding_configurations:EncodingConfigurations::default(),
#[cfg(all(feature = "support_tls",not(feature="use_io_uring")))]
tls_ports:vec![],
backlog:1028,
max_request_size:10000,
listeners_count:1,
worker_threads_count:worker_threads,
max_buffer_size_for_cache:65536,
default_read_buffer_size:READING_BUF_LEN,
default_write_buffer_size:WRITING_BUF_LEN,
default_body_buffer_size:EACH_REQUEST_BODY_READING_BUFFER,
max_cached_buffers_count:512
}
}
#[cfg(feature = "auto_encode_response")]
pub fn set_response_encoding_configuration(&mut self,conf:EncodingConfigurations){
self.responding_encoding_configurations = conf;
}
pub fn set_listeners_count(&mut self,c:usize){
self.listeners_count = c;
}
pub fn set_restriction_to_ips(&mut self,roll:RestrictionRule){
self.restricted_ips = Some(roll);
}
pub fn enable_core_affinity(&mut self){
self.core_affinity = true;
}
#[cfg(all(feature = "support_tls",not(feature="use_io_uring")))]
pub fn set_tls_certificate(&mut self,cert_path:&str,key_path:&str,bundle:Option<String>){
self.tls_certificate = Some(
TLSCertificate {
tls_cert:cert_path.to_string(),
tls_key:key_path.to_string(),
tls_ca_bundle:bundle
}
);
}
pub fn bind_multi_ports(ports:Vec<u16>)->Self {
let mut addresses = Vec::<(String,u16)>::new();
for port in ports {
addresses.push(("0.0.0.0".to_string(),port));
}
Self::bind_multi_addresses(addresses)
}
pub fn bind_port(port:u16)->Self {
Self::bind("0.0.0.0",port)
}
pub fn bind(link:&str,port:u16)->Self{
ServerConfigurations {
addresses:vec![(link.to_string(),port)],
..Self::default()
}
}
pub fn bind_multi_addresses(links:Vec<(String,u16)>)->Self{
ServerConfigurations {
addresses:links,
..Self::default()
}
}
}