| Crates.io | ferrotunnel-plugin |
| lib.rs | ferrotunnel-plugin |
| version | 0.5.0 |
| created_at | 2026-01-25 09:59:05.250999+00 |
| updated_at | 2026-01-25 09:59:05.250999+00 |
| description | Plugin system for FerroTunnel |
| homepage | https://github.com/MitulShah1/ferrotunnel |
| repository | https://github.com/MitulShah1/ferrotunnel |
| max_upload_size | |
| id | 2068466 |
| size | 45,246 |
This crate contains the core traits and infrastructure for the Ferrotunnel plugin system.
FerroTunnel supports a powerful trait-based plugin system that allows you to intercept and modify request/response traffic, enforce authentication, rate limiting, and more.
To create a new plugin, implement the Plugin trait from ferrotunnel-plugin.
use ferrotunnel_plugin::{Plugin, PluginAction, RequestContext, ResponseContext};
use async_trait::async_trait;
pub struct MyPlugin;
#[async_trait]
impl Plugin for MyPlugin {
fn name(&self) -> &str {
"my-plugin"
}
async fn on_request(
&self,
req: &mut http::Request<Vec<u8>>,
_ctx: &RequestContext,
) -> Result<PluginAction, Box<dyn std::error::Error + Send + Sync + 'static>> {
println!("Received request: {}", req.uri());
Ok(PluginAction::Continue)
}
}
on_request: Called before the request is forwarded to the tunnel.on_response: Called after the response is received from the tunnel.on_stream_data: Called when raw data flows through the stream (TCP mode).PluginAction::Continue: Allow the request to proceed to the next plugin or target.PluginAction::Reject { status, reason }: Stop processing and return an error response immediately.PluginAction::Respond { status, headers, body }: Return a custom response immediately.PluginAction::Modify: (Upcoming) Modify the request/response extensively.See ferrotunnel-plugin/src/builtin/ for built-in plugins (Logger, TokenAuth, RateLimit).
Check the examples/ directory for more:
hello_plugin.rs: Simple header injection.header_filter.rs: Removing sensitive headers.ip_blocklist.rs: Blocking requests by IP.You can test plugins in two ways:
Unit Tests: Mock RequestContext and assert on PluginAction results.
#[tokio::test]
async fn test_my_plugin() {
let plugin = MyPlugin::new();
let mut req = http::Request::builder().body(vec![]).unwrap();
let ctx = RequestContext { ... };
let action = plugin.on_request(&mut req, &ctx).await.unwrap();
assert_eq!(action, PluginAction::Continue);
}
Run Examples:
cargo run -p ferrotunnel-plugin --example hello_plugin
cargo run -p ferrotunnel-plugin --example header_filter
cargo run -p ferrotunnel-plugin --example ip_blocklist
Register your plugin in ferrotunnel-server/src/main.rs:
registry.register(Arc::new(RwLock::new(MyPlugin)));