bext-plugin-api 0.2.0

Plugin trait definitions and shared types for bext — the public ABI for plugin authors
Documentation
//! Middleware plugin trait and types for request/response interception.
//! Plugins can inspect or modify requests and optionally short-circuit
//! with a custom [`PluginResponse`].

use crate::types::priority;
use std::collections::HashMap;

/// Actions a middleware plugin can take during request processing.
#[derive(Debug)]
pub enum RequestAction {
    /// Continue to the next middleware / handler.
    Continue,
    /// Short-circuit with a custom response.
    Respond(PluginResponse),
}

/// A short-circuit HTTP response produced by a middleware plugin.
#[derive(Debug, Clone)]
pub struct PluginResponse {
    pub status: u16,
    pub headers: Vec<(String, String)>,
    pub body: Vec<u8>,
}

/// Request context passed to middleware plugins.
///
/// Pure data — no framework types. Middleware can read request metadata
/// and write to `extensions` to pass data between `on_request` and
/// `on_response`, or to downstream handlers.
#[derive(Debug)]
pub struct RequestContext {
    pub method: String,
    pub path: String,
    pub hostname: String,
    pub headers: Vec<(String, String)>,
    pub query_string: String,
    pub peer_ip: Option<String>,
    pub tenant_id: Option<String>,
    pub site_id: Option<String>,
    /// Mutable key-value store for passing plugin data through the
    /// request lifecycle. Middleware plugins can write here in `on_request`
    /// and read in `on_response`. Other plugins/handlers can also read.
    pub extensions: HashMap<String, String>,
}

/// Response headers that middleware plugins can mutate in `on_response`.
#[derive(Debug)]
pub struct ResponseHeaders {
    pub status: u16,
    pub headers: Vec<(String, String)>,
}

/// A plugin that hooks into the HTTP request/response lifecycle.
///
/// **Compile-time only** — no WASM overhead on every request.
///
/// Priority determines stack position. Built-in priorities:
/// CORS=100, RateLimit=200, Auth=300, Tenant=400, Tracing=500.
/// Plugin middlewares default to 600.
pub trait MiddlewarePlugin: Send + Sync {
    /// Unique identifier (e.g., `"security-headers"`).
    fn name(&self) -> &str;

    /// Stack position. Lower = runs earlier on request, later on response.
    /// Default: 600 (after all built-in middleware).
    fn priority(&self) -> u32 {
        priority::PLUGIN_DEFAULT
    }

    /// Called on each incoming request before the handler.
    ///
    /// Return `Ok(RequestAction::Continue)` to proceed, or
    /// `Ok(RequestAction::Respond(..))` to short-circuit.
    fn on_request(&self, ctx: &mut RequestContext) -> Result<RequestAction, String>;

    /// Called after the handler produces a response.
    ///
    /// Use this to inject headers, modify status, etc.
    fn on_response(
        &self,
        ctx: &RequestContext,
        headers: &mut ResponseHeaders,
    ) -> Result<(), String>;
}