Skip to main content

contentstack_api_client_rs/client/
config.rs

1use std::time::Duration;
2
3/// Represents the geographical regions supported by the Contentstack API.
4#[derive(Clone, Debug, PartialEq)]
5pub enum Region {
6    AwsNa,
7    AwsEu,
8    AwsAu,
9    AzureNa,
10    AzureEu,
11    GcpNa,
12    GcpEu,
13}
14
15/// The type of client being initialized.
16#[derive(Clone, Debug, PartialEq)]
17pub enum ClientType {
18    /// Content Delivery API (CDN).
19    Delivery,
20    /// Content Management API.
21    Management,
22}
23
24impl Region {
25    /// Returns the Delivery API (CDN) base URL for the current region.
26    pub fn delivery_base_url(&self) -> &'static str {
27        match &self {
28            Region::AwsNa => "https://cdn.contentstack.io",
29            Region::AwsEu => "https://eu-cdn.contentstack.com",
30            Region::AwsAu => "https://au-cdn.contentstack.com",
31            Region::AzureNa => "https://azure-na-cdn.contentstack.com",
32            Region::AzureEu => "https://azure-eu-cdn.contentstack.com",
33            Region::GcpNa => "https://gcp-na-cdn.contentstack.com",
34            Region::GcpEu => "https://gcp-eu-cdn.contentstack.com",
35        }
36    }
37
38    /// Returns the Management API base URL for the current region.
39    pub fn management_base_url(&self) -> &'static str {
40        match &self {
41            Region::AwsNa => "https://api.contentstack.io",
42            Region::AwsEu => "https://eu-api.contentstack.com",
43            Region::AwsAu => "https://au-api.contentstack.com",
44            Region::AzureNa => "https://azure-na-api.contentstack.com",
45            Region::AzureEu => "https://azure-eu-api.contentstack.com",
46            Region::GcpNa => "https://gcp-na-api.contentstack.com",
47            Region::GcpEu => "https://gcp-eu-api.contentstack.com",
48        }
49    }
50}
51
52/// Finalized configuration used by Contentstack clients.
53///
54/// This struct is typically constructed using [`ClientConfig::delivery`] or
55/// [`ClientConfig::management`].
56#[derive(Clone, Debug)]
57pub struct ClientConfig {
58    /// The base URL used for API requests.
59    pub base_url: String,
60    /// Your Contentstack stack API key.
61    pub api_key: String,
62    /// The token used for Management API authentication.
63    pub management_token: String,
64    /// The token used for Delivery API authentication.
65    pub delivery_token: String,
66    /// The publishing environment (e.g., "production"). Only used by the Delivery API.
67    pub environment: Option<String>,
68    /// The maximum duration to wait for a request to complete.
69    pub timeout: Duration,
70    /// The maximum number of concurrent connections allowed in the pool.
71    pub max_connections: usize,
72    /// The geographical region for the API.
73    pub region: Region,
74}
75
76/// Configuration options for initializing a `ClientConfig`.
77///
78/// Provides overrides for the default API endpoints, connection settings, and timeouts.
79///
80/// # Examples
81///
82/// ```
83/// use std::time::Duration;
84/// use contentstack_api_client_rs::{ClientOptions, Region};
85///
86/// let opts = ClientOptions {
87///     base_url: Some("https://custom-cdn.contentstack.com".to_string()),
88///     timeout: Some(Duration::from_secs(60)),
89///     max_connections: Some(100),
90///     region: Some(Region::AwsEu),
91/// };
92/// ```
93#[derive(Default, Clone, Debug)]
94pub struct ClientOptions {
95    /// Custom base URL for the API requests. If not provided, defaults to the region's URL.
96    pub base_url: Option<String>,
97    /// The maximum duration to wait for a request to complete. Defaults to 30 seconds.
98    pub timeout: Option<Duration>,
99    /// The maximum number of concurrent connections allowed. Defaults to 50.
100    pub max_connections: Option<usize>,
101    /// The geographical region for the Contentstack API. Defaults to AWS North America.
102    pub region: Option<Region>,
103}
104
105impl ClientOptions {
106    /// Returns the default configuration options for the given client type.
107    ///
108    /// The defaults are configured to use the AWS North America region,
109    /// a 30-second timeout, and a maximum of 50 concurrent connections.
110    ///
111    /// # Arguments
112    ///
113    /// * `client_type` - The type of client (Delivery or Management).
114    ///
115    /// # Examples
116    ///
117    /// ```
118    /// use contentstack_api_client_rs::client::config::{ClientOptions, ClientType};
119    ///
120    /// let defaults = ClientOptions::get_defaults(ClientType::Delivery);
121    /// assert_eq!(defaults.max_connections, Some(50));
122    /// ```
123    pub fn get_defaults(client_type: ClientType) -> ClientOptions {
124        let timeout: Duration = Duration::from_secs(30);
125        let max_connections = 50;
126
127        let base_url = match client_type {
128            ClientType::Delivery => Region::AwsNa.delivery_base_url(),
129            ClientType::Management => Region::AwsNa.management_base_url(),
130        };
131
132        ClientOptions {
133            base_url: Some(base_url.into()),
134            timeout: Some(timeout),
135            max_connections: Some(max_connections),
136            region: Some(Region::AwsNa),
137        }
138    }
139}
140
141impl ClientConfig {
142    /// Builds a `ClientConfig` configured for the Contentstack Delivery API.
143    ///
144    /// Initializes a configuration object using the provided API key, delivery token,
145    /// and environment. If `opts` is `None`, default settings are applied (AWS NA region,
146    /// 30-second timeout, 50 max connections).
147    ///
148    /// # Arguments
149    ///
150    /// * `api_key` - Your stack's API key
151    /// * `delivery_token` - Your stack's delivery token (read-only)
152    /// * `environment` - The name of the publishing environment
153    /// * `opts` - Optional configuration overrides (`ClientOptions`)
154    ///
155    /// # Examples
156    ///
157    /// ```
158    /// use contentstack_api_client_rs::client::config::ClientConfig;
159    ///
160    /// let config = ClientConfig::delivery("api_key", "delivery_token", "production", None);
161    /// assert_eq!(config.environment.as_deref(), Some("production"));
162    /// ```
163    pub fn delivery(
164        api_key: &str,
165        delivery_token: &str,
166        environment: &str,
167        opts: Option<ClientOptions>,
168    ) -> Self {
169        let defaults = ClientOptions::get_defaults(ClientType::Delivery);
170        let defaults = if let Some(config) = opts {
171            ClientOptions {
172                base_url: config.base_url.or(defaults.base_url),
173                timeout: config.timeout.or(defaults.timeout),
174                max_connections: config.max_connections.or(defaults.max_connections),
175                region: config.region.or(defaults.region),
176            }
177        } else {
178            defaults
179        };
180
181        Self {
182            base_url: defaults.base_url.expect("Base Url not provided"),
183            api_key: api_key.into(),
184            delivery_token: delivery_token.into(),
185            management_token: String::new(),
186            environment: Some(environment.into()),
187            timeout: defaults.timeout.unwrap_or(Duration::from_secs(30)),
188            max_connections: defaults.max_connections.unwrap_or(50),
189            region: defaults.region.expect("Region not provided"),
190        }
191    }
192
193    /// Builds a [`ClientConfig`] for the Management API.
194    ///
195    /// Defaults to AWS NA region (`https://api.contentstack.io`) if no
196    /// `base_url` or `region` override is provided. Management API requests
197    /// do not use an environment, so that field is left empty.
198    ///
199    /// # Arguments
200    ///
201    /// * `api_key` - Your stack's API key
202    /// * `management_token` - Stack management token
203    /// * `opts` - Optional configuration overrides (region, timeout, max connections)
204    pub fn management(api_key: &str, management_token: &str, opts: Option<ClientOptions>) -> Self {
205        let defaults = ClientOptions::get_defaults(ClientType::Management);
206
207        let defaults = if let Some(config) = opts {
208            ClientOptions {
209                base_url: config.base_url.or(defaults.base_url),
210                timeout: config.timeout.or(defaults.timeout),
211                max_connections: config.max_connections.or(defaults.max_connections),
212                region: config.region.or(defaults.region),
213            }
214        } else {
215            defaults
216        };
217
218        Self {
219            base_url: defaults.base_url.expect("Base Url not provided"),
220            api_key: api_key.into(),
221            delivery_token: String::new(),
222            management_token: management_token.into(),
223            environment: None,
224            timeout: defaults.timeout.unwrap_or(Duration::from_secs(30)),
225            max_connections: defaults.max_connections.unwrap_or(50),
226            region: defaults.region.expect("Region not provided"),
227        }
228    }
229}