tako/
plugins.rs

1#![cfg_attr(docsrs, doc(cfg(feature = "plugins")))]
2//! Plugin system for extending framework functionality with composable modules.
3//!
4//! This module provides the core plugin infrastructure for Tako, allowing developers
5//! to extend the framework with reusable components. Plugins can add middleware,
6//! modify routing behavior, or integrate external services. The `TakoPlugin` trait
7//! defines the interface all plugins must implement for registration and setup.
8//!
9//! Plugins can be applied at two levels:
10//! - **Router-level**: Applied globally to all routes using `router.plugin()`
11//! - **Route-level**: Applied to specific routes using `route.plugin()`
12//!
13//! # Examples
14//!
15//! ```rust
16//! use tako::plugins::TakoPlugin;
17//! use tako::router::Router;
18//! use tako::Method;
19//! use anyhow::Result;
20//!
21//! struct LoggingPlugin {
22//!     level: String,
23//! }
24//!
25//! impl TakoPlugin for LoggingPlugin {
26//!     fn name(&self) -> &'static str {
27//!         "logging"
28//!     }
29//!
30//!     fn setup(&self, _router: &Router) -> Result<()> {
31//!         println!("Setting up logging plugin with level: {}", self.level);
32//!         Ok(())
33//!     }
34//! }
35//!
36//! async fn handler(_req: tako::types::Request) -> &'static str {
37//!     "Hello"
38//! }
39//!
40//! // Router-level plugin (applied to all routes)
41//! let mut router = Router::new();
42//! router.plugin(LoggingPlugin { level: "info".to_string() });
43//!
44//! // Route-level plugin (applied to specific route only)
45//! let route = router.route(Method::GET, "/api/data", handler);
46//! route.plugin(LoggingPlugin { level: "debug".to_string() });
47//! ```
48
49use anyhow::Result;
50
51use crate::router::Router;
52
53/// Compression plugin for automatic response compression.
54pub mod compression;
55
56/// CORS (Cross-Origin Resource Sharing) plugin for handling cross-origin requests.
57pub mod cors;
58
59/// Rate limiting plugin for controlling request frequency.
60pub mod rate_limiter;
61
62/// Metrics/tracing plugin for integrating with systems like Prometheus or OpenTelemetry.
63pub mod metrics;
64
65/// Idempotency-Key based request de-duplication plugin.
66pub mod idempotency;
67
68/// Trait for implementing Tako framework plugins.
69///
70/// Plugins extend the framework's functionality by implementing this trait. They can
71/// add middleware, modify routing behavior, register handlers, or integrate external
72/// services. All plugins must be thread-safe and have a static lifetime.
73///
74/// Plugins can be applied at both router and route levels:
75/// - **Router-level**: Use `router.plugin()` to apply globally
76/// - **Route-level**: Use `route.plugin()` to apply to specific routes
77///
78/// # Examples
79///
80/// ```rust
81/// use tako::plugins::TakoPlugin;
82/// use tako::router::Router;
83/// use tako::Method;
84/// use anyhow::Result;
85///
86/// struct CachePlugin {
87///     ttl_seconds: u64,
88/// }
89///
90/// impl TakoPlugin for CachePlugin {
91///     fn name(&self) -> &'static str {
92///         "cache"
93///     }
94///
95///     fn setup(&self, router: &Router) -> Result<()> {
96///         // Add middleware to the router
97///         router.middleware(|req, next| async move {
98///             // Cache logic here
99///             next.run(req).await
100///         });
101///         Ok(())
102///     }
103/// }
104///
105/// async fn handler(_req: tako::types::Request) -> &'static str {
106///     "Hello"
107/// }
108///
109/// // Router-level usage
110/// let mut router = Router::new();
111/// router.plugin(CachePlugin { ttl_seconds: 300 });
112///
113/// // Route-level usage
114/// let route = router.route(Method::GET, "/api/data", handler);
115/// route.plugin(CachePlugin { ttl_seconds: 600 });
116/// ```
117pub trait TakoPlugin: Send + Sync + 'static {
118  /// Returns the unique name identifier for this plugin.
119  fn name(&self) -> &'static str;
120
121  /// Configures and initializes the plugin with the given router.
122  fn setup(&self, router: &Router) -> Result<()>;
123}