bext_plugin_api/middleware.rs
1//! Middleware plugin trait and types for request/response interception.
2//! Plugins can inspect or modify requests and optionally short-circuit
3//! with a custom [`PluginResponse`].
4
5use crate::types::priority;
6use std::collections::HashMap;
7
8/// Actions a middleware plugin can take during request processing.
9#[derive(Debug)]
10pub enum RequestAction {
11 /// Continue to the next middleware / handler.
12 Continue,
13 /// Short-circuit with a custom response.
14 Respond(PluginResponse),
15}
16
17/// A short-circuit HTTP response produced by a middleware plugin.
18#[derive(Debug, Clone)]
19pub struct PluginResponse {
20 pub status: u16,
21 pub headers: Vec<(String, String)>,
22 pub body: Vec<u8>,
23}
24
25/// Request context passed to middleware plugins.
26///
27/// Pure data — no framework types. Middleware can read request metadata
28/// and write to `extensions` to pass data between `on_request` and
29/// `on_response`, or to downstream handlers.
30#[derive(Debug)]
31pub struct RequestContext {
32 pub method: String,
33 pub path: String,
34 pub hostname: String,
35 pub headers: Vec<(String, String)>,
36 pub query_string: String,
37 pub peer_ip: Option<String>,
38 pub tenant_id: Option<String>,
39 pub site_id: Option<String>,
40 /// Mutable key-value store for passing plugin data through the
41 /// request lifecycle. Middleware plugins can write here in `on_request`
42 /// and read in `on_response`. Other plugins/handlers can also read.
43 pub extensions: HashMap<String, String>,
44}
45
46/// Response headers that middleware plugins can mutate in `on_response`.
47#[derive(Debug)]
48pub struct ResponseHeaders {
49 pub status: u16,
50 pub headers: Vec<(String, String)>,
51}
52
53/// A plugin that hooks into the HTTP request/response lifecycle.
54///
55/// **Compile-time only** — no WASM overhead on every request.
56///
57/// Priority determines stack position. Built-in priorities:
58/// CORS=100, RateLimit=200, Auth=300, Tenant=400, Tracing=500.
59/// Plugin middlewares default to 600.
60pub trait MiddlewarePlugin: Send + Sync {
61 /// Unique identifier (e.g., `"security-headers"`).
62 fn name(&self) -> &str;
63
64 /// Stack position. Lower = runs earlier on request, later on response.
65 /// Default: 600 (after all built-in middleware).
66 fn priority(&self) -> u32 {
67 priority::PLUGIN_DEFAULT
68 }
69
70 /// Called on each incoming request before the handler.
71 ///
72 /// Return `Ok(RequestAction::Continue)` to proceed, or
73 /// `Ok(RequestAction::Respond(..))` to short-circuit.
74 fn on_request(&self, ctx: &mut RequestContext) -> Result<RequestAction, String>;
75
76 /// Called after the handler produces a response.
77 ///
78 /// Use this to inject headers, modify status, etc.
79 fn on_response(
80 &self,
81 ctx: &RequestContext,
82 headers: &mut ResponseHeaders,
83 ) -> Result<(), String>;
84}