Skip to main content

gen_linkedin/
client.rs

1use reqwest::{header, Client as HttpClient};
2use url::Url;
3
4use crate::{auth::TokenProvider, Error};
5
6const DEFAULT_BASE: &str = "https://api.linkedin.com";
7
8/// A thin HTTP client wrapper configured for LinkedIn's API.
9pub struct Client<TP: TokenProvider> {
10    http: HttpClient,
11    base: Url,
12    token_provider: TP,
13    user_agent: String,
14}
15
16impl<TP: TokenProvider> Client<TP> {
17    /// Constructs a new client using the provided token provider.
18    pub fn new(token_provider: TP) -> Result<Self, Error> {
19        let http = HttpClient::builder().build()?;
20        let base = Url::parse(DEFAULT_BASE).map_err(|e| Error::Config(e.to_string()))?;
21        Ok(Self {
22            http,
23            base,
24            token_provider,
25            user_agent: format!("gen-linkedin/{}", env!("CARGO_PKG_VERSION")),
26        })
27    }
28
29    /// Override the base URL (useful for testing).
30    #[must_use]
31    pub fn with_base(mut self, base: Url) -> Self {
32        self.base = base;
33        self
34    }
35
36    /// Retrieve the current bearer token from the provider.
37    pub fn bearer(&self) -> Result<String, Error> {
38        self.token_provider.bearer_token()
39    }
40
41    /// The underlying reqwest client.
42    pub fn http(&self) -> &HttpClient {
43        &self.http
44    }
45
46    /// The base API URL.
47    pub fn base(&self) -> &Url {
48        &self.base
49    }
50
51    /// The default User-Agent used in requests.
52    pub fn user_agent(&self) -> &str {
53        &self.user_agent
54    }
55
56    pub(crate) fn auth_headers(&self) -> Result<header::HeaderMap, Error> {
57        let mut headers = header::HeaderMap::new();
58        headers.insert(
59            header::AUTHORIZATION,
60            format!("Bearer {}", self.bearer()?).parse().unwrap(),
61        );
62        headers.insert(header::USER_AGENT, self.user_agent.parse().unwrap());
63        Ok(headers)
64    }
65}