Skip to main content

better_fetch/
plugin.rs

1use async_trait::async_trait;
2use url::Url;
3
4use crate::hooks::Hooks;
5use crate::Result;
6
7/// Prepared request state passed to plugin `init`.
8#[derive(Debug, Clone)]
9pub struct PreparedRequest {
10    pub url: Url,
11    pub path: String,
12}
13
14/// Plugin extension point for better-fetch.
15#[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/// Ordered plugin list.
29#[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}