4 stable releases

new 1.0.3 Feb 17, 2026
1.0.2 Feb 11, 2026
0.9.6 Feb 1, 2026
0.9.5 Jan 31, 2026
0.5.0 Jan 25, 2026

#12 in #extensible


Used in 5 crates (4 directly)

MIT/Apache

41KB
808 lines

Ferrotunnel Plugin System

Crates.io Documentation License

This crate contains the core traits and infrastructure for the Ferrotunnel plugin system.

Plugin Developer Guide

FerroTunnel supports a trait-based plugin system for intercepting and modifying request/response traffic, authentication, rate limiting, and more.

Quick Start

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)
    }
}

Plugin Lifecycle

  1. Init: Called when the server starts. Use this to set up database connections or other resources.
  2. Hooks:
    • 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).
  3. Shutdown: Called when the server shuts down.

Plugin Actions

  • 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.

Examples

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.

Testing

You can test plugins in two ways:

  1. 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);
    }
    
  2. 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
    

Usage

Register your plugin in ferrotunnel-cli/src/commands/server.rs:

registry.register(Arc::new(RwLock::new(MyPlugin)));

Dependencies

~10–16MB
~198K SLoC