Skip to main content

hooksmith_core/
client.rs

1use reqwest::Client;
2use serde::Serialize;
3
4/// A thin wrapper around [`reqwest::Client`] shared by all hooksmith service crates.
5///
6/// Service crates (e.g. `discord_hook`, `slack_hook`) hold one of these,
7/// configure it at construction time, and call [`HttpClient::post_json`] to
8/// fire requests.
9///
10/// **TLS configuration** is the responsibility of the service crate — build a
11/// [`reqwest::Client`] with your chosen TLS backend and pass it in via
12/// [`HttpClient::with_reqwest`].
13pub struct HttpClient {
14    inner: Client,
15}
16
17impl HttpClient {
18    /// Create a client backed by a freshly-constructed [`reqwest::Client`].
19    ///
20    /// A 30-second request timeout is applied by default so that a slow or
21    /// unresponsive endpoint can never hang your application indefinitely.
22    /// Override this by building your own [`reqwest::Client`] and passing it
23    /// to [`HttpClient::with_reqwest`].
24    pub fn new() -> Self {
25        let inner = Client::builder()
26            .timeout(std::time::Duration::from_secs(30))
27            .build()
28            .expect("failed to initialise reqwest client — TLS backend unavailable");
29        Self { inner }
30    }
31
32    /// Wrap an existing [`reqwest::Client`].
33    ///
34    /// Use this to share a connection pool or inject custom configuration
35    /// (timeouts, proxies, etc.) across your application.
36    pub fn with_reqwest(client: Client) -> Self {
37        Self { inner: client }
38    }
39
40    /// POST `body` serialized as JSON to `url` and return the raw response.
41    pub async fn post_json(
42        &self,
43        url: &str,
44        body: &impl Serialize,
45    ) -> Result<reqwest::Response, reqwest::Error> {
46        self.inner.post(url).json(body).send().await
47    }
48
49    /// Access the underlying [`reqwest::Client`] for advanced use-cases.
50    pub fn inner(&self) -> &Client {
51        &self.inner
52    }
53}
54
55impl Default for HttpClient {
56    fn default() -> Self {
57        Self::new()
58    }
59}