messagebird_async/sms/async/
send.rs1use super::super::*;
5
6use futures::*;
7use hyper;
8
9use hyper_rustls;
10
11use std::env;
12use std::fmt;
13use std::marker::PhantomData;
14use std::ops::Deref;
15
16#[derive(Debug, Clone)]
20pub struct AccessKey(String);
21
22impl Deref for AccessKey {
23 type Target = String;
24 fn deref(&self) -> &Self::Target {
25 &self.0
26 }
27}
28
29impl FromStr for AccessKey {
30 type Err = MessageBirdError;
31 fn from_str(s: &str) -> Result<Self, Self::Err> {
32 Ok(AccessKey(s.to_string()))
34 }
35}
36
37impl From<String> for AccessKey {
38 fn from(s: String) -> Self {
39 AccessKey(s)
40 }
41}
42
43impl fmt::Display for AccessKey {
44 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
45 write!(f, "{}", self.0)
46 }
47}
48
49impl AccessKey {
50 pub fn from_env() -> Result<AccessKey, MessageBirdError> {
51 let raw =
52 env::var("MESSAGEBIRD_ACCESSKEY").map_err(|_e| MessageBirdError::AccessKeyError {
53 msg: "env".to_string(),
54 })?;
55 AccessKey::from_str(raw.as_str())
56 }
57}
58
59pub type RequestMessageList = Request<parameter::list::ListParameters, MessageList>;
61
62pub type RequestView = Request<parameter::view::ViewParameters, Message>;
64
65pub type RequestSend = Request<parameter::send::SendParameters, Message>;
67
68pub struct Request<T, R> {
74 future: Box<dyn Future<Item = R, Error = MessageBirdError>>,
75 phantom: PhantomData<T>,
76}
77
78impl<T, R> Future for Request<T, R> {
79 type Item = R;
80 type Error = MessageBirdError;
81 fn poll(&mut self) -> Result<Async<Self::Item>, Self::Error> {
82 self.future.poll()
83 }
84}
85
86fn request_future_with_json_response<R>(
87 client: &mut hyper::Client<
88 hyper_rustls::HttpsConnector<hyper::client::HttpConnector>,
89 hyper::Body,
90 >,
91 request: hyper::Request<hyper::Body>,
92) -> impl Future<Item = R, Error = MessageBirdError>
93where
94 R: 'static + Sized + Send + Sync + for<'de> serde::de::Deserialize<'de> + std::fmt::Debug,
95{
96 debug!("request {:?}", request);
97 let fut = client
98 .request(request)
99 .map_err(|e: hyper::Error| {
100 debug!("request {:?}", e);
101 MessageBirdError::RequestError
102 })
103 .and_then(|response: hyper::Response<hyper::Body>| {
104 let status = response.status();
105 debug!("rest status code: {}", status);
106
107 futures::future::ok(response)
108 })
116 .and_then(|response: hyper::Response<hyper::Body>| {
117 let status = response.status();
118 let body: hyper::Body = response.into_body();
119 body.concat2()
120 .map_err(|e| {
121 debug!("body concat {:?}", e);
122 MessageBirdError::RequestError
123 })
124 .map(move |x| (status, x))
125 })
127 .and_then(|(status, body): (_, hyper::Chunk)| {
129 debug!("response: {:?}", String::from_utf8(body.to_vec()).unwrap());
130 match status {
131 hyper::StatusCode::OK | hyper::StatusCode::CREATED => {
132 match serde_json::from_slice::<R>(&body).map_err(|e| {
134 debug!("Failed to parse response body: {:?}", e);
135 MessageBirdError::ParseError
136 }) {
137 Err(e) => futures::future::err(e),
138 Ok(x) => {
139 debug!("Parsed response {:?}", x);
140 futures::future::ok(x)
141 }
142 }
143 }
144 _ => match serde_json::from_slice::<ServiceErrors>(&body).map_err(|e| {
145 debug!("Failed to parse response body: {:?}", e);
146 MessageBirdError::ParseError
147 }) {
148 Err(e) => futures::future::err(e),
149 Ok(service_errors) => {
150 let service_errors = service_errors.into();
151 debug!("Parsed error response {:?}", service_errors);
152 futures::future::err(MessageBirdError::ServiceError(service_errors))
153 }
154 },
155 }
156 });
157 fut
158}
159
160impl<P, R> Request<P, R>
161where
162 P: Send + Query,
163 R: 'static + Send + Sync + for<'de> serde::de::Deserialize<'de> + std::fmt::Debug,
164{
165 pub fn new(parameters: &P, accesskey: &AccessKey) -> Self {
166 let https = hyper_rustls::HttpsConnector::new(4);
167 let mut client: hyper::Client<_, hyper::Body> = hyper::Client::builder().build(https);
168
169 let mut request = hyper::Request::builder();
170 request.uri(parameters.uri());
171 request.method(parameters.method());
172 request.header(
173 hyper::header::AUTHORIZATION,
174 format!("AccessKey {}", accesskey),
175 );
176 debug!("{:?}", request);
177
178 let request: hyper::Request<_> = if parameters.method() == hyper::Method::POST {
180 request.header(
181 hyper::header::CONTENT_TYPE,
182 format!("application/x-www-form-urlencoded"),
183 );
184 parameters
185 .uri()
186 .query()
187 .map(|body: &str| {
188 let body = body.to_string();
189 request.header(hyper::header::CONTENT_LENGTH, format!("{}", body.len()));
190 request.body(body.into()).unwrap()
191 })
192 .unwrap_or_else(|| {
193 request.header(hyper::header::CONTENT_LENGTH, format!("{}", 0));
194 request.body(hyper::Body::empty()).unwrap()
195 })
196 } else {
197 request.header(hyper::header::CONTENT_LENGTH, format!("{}", 0));
198 request.body(hyper::Body::empty()).unwrap()
199 };
200
201 let future = request_future_with_json_response::<R>(&mut client, request);
202
203 let future = Box::new(future);
205 Self {
206 future,
207 phantom: PhantomData,
208 }
209 }
210}