1use async_trait::async_trait;
2use url::Url;
3
4use crate::hooks::Hooks;
5use crate::Result;
6
7#[derive(Debug, Clone)]
9pub struct PreparedRequest {
10 pub url: Url,
11 pub path: String,
12}
13
14#[async_trait]
16pub trait Plugin: Send + Sync {
17 fn id(&self) -> &'static str;
18
19 async fn init(&self, _prepared: &mut PreparedRequest) -> Result<()> {
20 Ok(())
21 }
22
23 fn hooks(&self) -> Hooks {
24 Hooks::default()
25 }
26}
27
28#[derive(Default)]
30pub struct PluginRegistry {
31 plugins: Vec<Box<dyn Plugin>>,
32}
33
34impl PluginRegistry {
35 pub fn new() -> Self {
36 Self::default()
37 }
38
39 pub fn register<P: Plugin + 'static>(mut self, plugin: P) -> Self {
40 self.plugins.push(Box::new(plugin));
41 self
42 }
43
44 pub fn push(&mut self, plugin: Box<dyn Plugin>) {
45 self.plugins.push(plugin);
46 }
47
48 pub fn plugins(&self) -> &[Box<dyn Plugin>] {
49 &self.plugins
50 }
51
52 pub(crate) async fn run_init_all(&self, prepared: &mut PreparedRequest) -> Result<()> {
53 for plugin in &self.plugins {
54 plugin.init(prepared).await?;
55 }
56 Ok(())
57 }
58
59 pub(crate) fn merged_hooks(&self) -> Hooks {
60 let mut hooks = Hooks::default();
61 for plugin in &self.plugins {
62 hooks = hooks.merge(plugin.hooks());
63 }
64 hooks
65 }
66}