postmark_client/
client.rs1use reqwest::{Response, StatusCode};
2use serde::de::DeserializeOwned;
3use serde::Serialize;
4
5use crate::errors::PostmarkClientError;
6use crate::types::APIError;
7use crate::{errors, Result};
8
9const POSTMARK_API_URL_BASE: &str = "https://api.postmarkapp.com";
10const POSTMARK_TOKEN_HEADER: &str = "X-Postmark-Server-Token";
11
12pub struct Client {
19 http_client: reqwest::Client,
20 token: String,
21}
22
23impl Client {
24 pub fn new(token: String) -> Client {
26 Client {
27 http_client: reqwest::Client::new(),
28 token,
29 }
30 }
31 pub fn new_with_client(token: String, http_client: reqwest::Client) -> Client {
33 Client { http_client, token }
34 }
35 async fn extract_error(response: Response) -> errors::PostmarkClientError {
40 let status = response.status();
41 match status {
42 StatusCode::UNAUTHORIZED => PostmarkClientError::Unauthorized,
43 StatusCode::NOT_FOUND => PostmarkClientError::RequestToLarge,
44 StatusCode::UNPROCESSABLE_ENTITY => {
45 let data = response.json::<APIError>().await;
46 match data {
47 Err(e) => PostmarkClientError::Reqwest(e),
48 Ok(e) => PostmarkClientError::UnprocessableEntity(e),
49 }
50 }
51 StatusCode::TOO_MANY_REQUESTS => PostmarkClientError::RateLimitExceeded,
52 StatusCode::INTERNAL_SERVER_ERROR => PostmarkClientError::InternalServerError,
53 StatusCode::SERVICE_UNAVAILABLE => PostmarkClientError::ServiceUnavailable,
54 _ => PostmarkClientError::UnknownPostmarkStatus(status),
55 }
56 }
57
58 pub(crate) async fn get<R>(&self, path: &str) -> Result<R>
59 where
60 R: DeserializeOwned,
61 {
62 let response = self
63 .http_client
64 .get(format!("{:}{:}", POSTMARK_API_URL_BASE, path))
65 .header(POSTMARK_TOKEN_HEADER, &self.token)
66 .send()
67 .await?;
68
69 if !response.status().is_success() {
70 return Err(Client::extract_error(response).await);
71 }
72
73 Ok(response.json::<R>().await?)
74 }
75
76 pub(crate) async fn get_with_query<Q, R>(&self, path: &str, query: &Q) -> Result<R>
77 where
78 Q: Serialize + ?Sized,
79 R: DeserializeOwned,
80 {
81 let response = self
82 .http_client
83 .get(format!("{:}{:}", POSTMARK_API_URL_BASE, path))
84 .header(POSTMARK_TOKEN_HEADER, &self.token)
85 .query(query)
86 .send()
87 .await?;
88
89 if !response.status().is_success() {
90 return Err(Client::extract_error(response).await);
91 }
92
93 Ok(response.json::<R>().await?)
94 }
95
96 pub(crate) async fn post<B, R>(&self, path: &str, body: &B) -> Result<R>
97 where
98 B: Serialize + ?Sized,
99 R: DeserializeOwned,
100 {
101 let response = self
102 .http_client
103 .post(format!("{:}{:}", POSTMARK_API_URL_BASE, path))
104 .header(POSTMARK_TOKEN_HEADER, &self.token)
105 .json(body)
106 .send()
107 .await?;
108
109 if !response.status().is_success() {
110 return Err(Client::extract_error(response).await);
111 }
112
113 Ok(response.json::<R>().await?)
114 }
115
116 pub(crate) async fn put<R>(&self, path: &str) -> Result<R>
117 where
118 R: DeserializeOwned,
119 {
120 let response = self
121 .http_client
122 .post(format!("{:}{:}", POSTMARK_API_URL_BASE, path))
123 .header(POSTMARK_TOKEN_HEADER, &self.token)
124 .send()
125 .await?;
126
127 if !response.status().is_success() {
128 return Err(Client::extract_error(response).await);
129 }
130
131 Ok(response.json::<R>().await?)
132 }
133}