use crate::engine::interfaces::Plugin;
use crate::plugins::l4::{
abort::AbortConnectionPlugin,
proxy::{domain::ProxyDomainPlugin, ip::TransparentProxyPlugin, node::ProxyNodePlugin},
};
use crate::plugins::l7::response::SendResponsePlugin;
use crate::plugins::l7::{
cgi::CgiPlugin, static_files::StaticPlugin, upstream::FetchUpstreamPlugin,
};
use crate::plugins::protocol::detect::ProtocolDetectPlugin;
use crate::plugins::{
middleware::{
matcher::CommonMatchPlugin,
ratelimit::{KeywordRateLimitMinPlugin, KeywordRateLimitSecPlugin},
},
protocol::upgrader::upgrade::UpgradePlugin,
};
use arc_swap::ArcSwap;
use dashmap::DashMap;
use once_cell::sync::Lazy;
use std::sync::Arc;
static INTERNAL_PLUGIN_REGISTRY: Lazy<DashMap<String, Arc<dyn Plugin>>> = Lazy::new(|| {
let registry = DashMap::new();
let transparent_proxy = Arc::new(TransparentProxyPlugin);
let mut plugins: Vec<Arc<dyn Plugin>> = vec![
Arc::new(ProtocolDetectPlugin),
Arc::new(CommonMatchPlugin),
Arc::new(AbortConnectionPlugin),
transparent_proxy.clone(),
Arc::new(ProxyNodePlugin),
Arc::new(ProxyDomainPlugin),
Arc::new(UpgradePlugin),
#[cfg(any(feature = "h2upstream", feature = "h3upstream"))]
Arc::new(FetchUpstreamPlugin),
Arc::new(CgiPlugin),
Arc::new(SendResponsePlugin),
];
#[cfg(feature = "ratelimit")]
{
plugins.push(Arc::new(KeywordRateLimitSecPlugin));
plugins.push(Arc::new(KeywordRateLimitMinPlugin));
}
#[cfg(feature = "cgi")]
{
plugins.push(Arc::new(CgiPlugin));
}
#[cfg(feature = "static")]
{
plugins.push(Arc::new(StaticPlugin));
}
for plugin in plugins {
registry.insert(plugin.name().to_owned(), plugin);
}
registry.insert(
"internal.transport.proxy.transparent".to_owned(),
transparent_proxy,
);
registry
});
static EXTERNAL_PLUGIN_REGISTRY: Lazy<ArcSwap<DashMap<String, Arc<dyn Plugin>>>> =
Lazy::new(|| ArcSwap::new(Arc::new(DashMap::new())));
pub static EXTERNAL_PLUGIN_STATUS: Lazy<DashMap<String, Result<(), String>>> =
Lazy::new(DashMap::new);
pub static EXTERNAL_PLUGIN_FAILURES: Lazy<DashMap<String, std::time::Instant>> =
Lazy::new(DashMap::new);
#[must_use]
pub fn get_plugin(name: &str) -> Option<Arc<dyn Plugin>> {
get_internal_plugin(name).or_else(|| get_external_plugin(name))
}
pub fn get_internal_plugin(name: &str) -> Option<Arc<dyn Plugin>> {
INTERNAL_PLUGIN_REGISTRY
.get(name)
.map(|entry| entry.value().clone())
}
pub fn get_external_plugin(name: &str) -> Option<Arc<dyn Plugin>> {
let external_plugins = EXTERNAL_PLUGIN_REGISTRY.load();
external_plugins
.get(name)
.map(|plugin| plugin.value().clone())
}
pub fn list_external_plugins() -> Vec<Arc<dyn Plugin>> {
let external_plugins = EXTERNAL_PLUGIN_REGISTRY.load();
external_plugins
.iter()
.map(|entry| entry.value().clone())
.collect()
}
pub fn load_external_plugins(new_plugins: DashMap<String, Arc<dyn Plugin>>) {
EXTERNAL_PLUGIN_REGISTRY.store(Arc::new(new_plugins));
}
pub fn clear_external_plugins() {
EXTERNAL_PLUGIN_REGISTRY.store(Arc::new(DashMap::new()));
}