api_client_framework/
endpoint.rs

1use serde::{Deserialize, Serialize};
2use std::{borrow::Cow, fmt::Debug};
3use url::Url;
4
5/// Represents a specification for an API call that can be built into an HTTP request and sent.
6/// New endpoints should implement this trait.
7///
8/// If the request succeeds, the call will resolve to a `Response`.
9pub trait Endpoint {
10    type Response: for<'a> Deserialize<'a> + Debug;
11
12    /// The HTTP Method used for this endpoint (e.g. GET, PATCH, DELETE)
13    fn method(&self) -> reqwest::Method;
14
15    /// The relative URL path for this endpoint
16    fn path(&self) -> String;
17
18    /// The url-encoded query string associated with this endpoint. Defaults to `None`.
19    ///
20    /// Implementors should inline this.
21    #[inline]
22    fn query(&self) -> Option<String> {
23        None
24    }
25
26    /// The set of headers to be sent with request. Defaults to `None`.
27    ///
28    /// Implementors should inline this.
29    #[inline]
30    fn headers(&self) -> Option<reqwest::header::HeaderMap> {
31        None
32    }
33
34    /// The HTTP body associated with this endpoint. If not implemented, defaults to `None`.
35    ///
36    /// Implementors should inline this.
37    #[inline]
38    fn body(&self) -> Option<String> {
39        None
40    }
41
42    /// Builds and returns a formatted full URL, including query, for the endpoint.
43    ///
44    /// Implementors should generally not override this.
45    fn url(&self, base_url: &Url) -> Url {
46        let mut url = base_url.join(&self.path()).unwrap();
47        url.set_query(self.query().as_deref());
48        url
49    }
50
51    /// If `body` is populated, indicates the body MIME type (defaults to JSON).
52    ///
53    /// Implementors generally do not need to override this.
54    fn content_type(&self) -> Cow<'static, str> {
55        Cow::Borrowed("application/json")
56    }
57}
58
59/// A utility function for serializing parameters into a URL query string.
60#[inline]
61pub fn serialize_query<Q: Serialize>(q: &Q) -> Option<String> {
62    serde_urlencoded::to_string(q).ok()
63}