use log::*;
use crate::message::stomp_message::StompMessage;
use crate::workflow::context::Context;
use crate::workflow::filter::{HttpFilter, HttpError};
use crate::workflow::filter::http::get::GetFilter;
use crate::workflow::filter::http::upgrade::UpgradeFilter;
use crate::workflow::filter::http::version::VersionFilter;
use crate::workflow::filter::http::health_check::HealthCheckFilter;
use crate::workflow::filter::http::not_found::NotFoundFilter;
use crate::workflow::filter::http::closure::ClosureFilter;
lazy_static! {
pub static ref FILTER_CHAIN_STATIC: FilterChain = FilterChain {
chain: build_filter_chain()
};
}
static mut CHAIN: Vec<(Box<dyn HttpFilter + Sync>, usize)> = Vec::new();
static mut INITIALIZED: bool = false;
static DEFAULT_INSERT_POINT: usize = 3;
pub fn insert_http_filter(filter: Box<dyn HttpFilter + Sync>) {
unsafe {
if INITIALIZED {
panic!("Cannot insert filters after the server is initialized");
}
CHAIN.push((filter, DEFAULT_INSERT_POINT));
}
}
pub fn insert_http_filter_at(filter: Box<dyn HttpFilter + Sync>, at: usize) {
unsafe {
if INITIALIZED {
panic!("Cannot insert filters after the server is initialized");
}
CHAIN.push((filter, at));
}
}
pub fn insert_http(closure: fn(&mut Context, message: &mut StompMessage) -> Result<bool, HttpError>) {
unsafe {
if INITIALIZED {
panic!("Cannot insert filters after the server is initialized");
}
insert_http_filter(Box::new(ClosureFilter::new(closure)));
}
}
pub struct FilterChain {
chain: Vec<Box<dyn HttpFilter + Sync>>,
}
pub fn build_filter_chain() -> Vec<Box<dyn HttpFilter + Sync>> {
let mut route: Vec<Box<dyn HttpFilter + Sync>> = vec![
Box::new(VersionFilter::new()),
Box::new(UpgradeFilter::new()),
Box::new(GetFilter::new()),
Box::new(HealthCheckFilter::new()),
Box::new(NotFoundFilter::new()),
];
unsafe {
while CHAIN.len() > 0 {
let filter = CHAIN.remove(CHAIN.len() - 1);
route.insert(filter.1, filter.0);
}
INITIALIZED = true;
}
for filter in route.iter_mut() {
filter.init();
info!("{:?}.init()", filter);
}
debug!("HTTP init finished");
route
}
pub fn route_http(mut ctx: &mut Context, message: &mut StompMessage) -> Result<(), ()> {
for f in &FILTER_CHAIN_STATIC.chain {
match f.do_filter(&mut ctx, message) {
Ok(false) => {
},
Ok(true) => {
break;
},
Err(fe) => {
if let Some(log_message) = fe.log_message {
warn!("{}", log_message);
}
return Err(());
}
}
}
return Ok(());
}