1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error<T>
where
T: std::error::Error + 'static,
{
#[error("request failed")]
Reqwest(#[source] T),
#[error("HTTP error")]
Http(#[source] http::Error),
#[error("I/O error")]
Io(#[source] std::io::Error),
#[error("Other error: {}", _0)]
Other(String),
}
#[cfg(not(target_arch = "wasm32"))]
pub use blocking::http_client;
#[cfg(not(target_arch = "wasm32"))]
pub type HttpClientError = Error<blocking::reqwest::Error>;
pub use async_client::async_http_client;
pub type AsyncHttpClientError = Error<reqwest::Error>;
#[cfg(not(target_arch = "wasm32"))]
mod blocking {
use super::super::{HttpRequest, HttpResponse};
use super::Error;
pub use reqwest;
use reqwest::blocking;
use reqwest::redirect::Policy as RedirectPolicy;
use std::io::Read;
pub fn http_client(request: HttpRequest) -> Result<HttpResponse, Error<reqwest::Error>> {
let client = blocking::Client::builder()
.redirect(RedirectPolicy::none())
.build()
.map_err(Error::Reqwest)?;
#[cfg(feature = "reqwest")]
let mut request_builder = client
.request(request.method, request.url.as_str())
.body(request.body);
for (name, value) in &request.headers {
request_builder = request_builder.header(name.as_str(), value.as_bytes());
}
let mut response = client
.execute(request_builder.build().map_err(Error::Reqwest)?)
.map_err(Error::Reqwest)?;
let mut body = Vec::new();
response.read_to_end(&mut body).map_err(Error::Io)?;
#[cfg(feature = "reqwest")]
{
Ok(HttpResponse {
status_code: response.status(),
headers: response.headers().to_owned(),
body,
})
}
}
}
mod async_client {
use super::super::{HttpRequest, HttpResponse};
use super::Error;
pub use reqwest;
pub async fn async_http_client(
request: HttpRequest,
) -> Result<HttpResponse, Error<reqwest::Error>> {
let client = {
let builder = reqwest::Client::builder();
#[cfg(not(target_arch = "wasm32"))]
let builder = builder.redirect(reqwest::redirect::Policy::none());
builder.build().map_err(Error::Reqwest)?
};
let mut request_builder = client
.request(request.method, request.url.as_str())
.body(request.body);
for (name, value) in &request.headers {
request_builder = request_builder.header(name.as_str(), value.as_bytes());
}
let request = request_builder.build().map_err(Error::Reqwest)?;
let response = client.execute(request).await.map_err(Error::Reqwest)?;
let status_code = response.status();
let headers = response.headers().to_owned();
let chunks = response.bytes().await.map_err(Error::Reqwest)?;
Ok(HttpResponse {
status_code,
headers,
body: chunks.to_vec(),
})
}
}