1#![allow(unused)]
2
3mod json {
4 pub use json::*;
5}
6
7pub use reqwest::*;
8use std::collections::HashMap;
9use std::fmt::{Debug, Formatter};
10use std::net::SocketAddr;
11use std::sync::Arc;
12use std::time::Duration;
13use ::json::JsonValue;
14use serde::{Deserialize, Serialize};
15use crate::errors::{HttpError, ErrorCode, HttpResult};
16use reqwest::dns::Resolve;
17use reqwest::header::{CONTENT_TYPE, HeaderMap, HeaderName, HeaderValue};
18
19pub async fn http_post_request(url: &str, param: Vec<u8>, content_type: Option<&str>) -> HttpResult<(Vec<u8>, Option<String>)> {
20 let mut request_builder = reqwest::Client::builder().no_proxy().build().unwrap().post(url);
21 if content_type.is_some() {
22 request_builder = request_builder.header(CONTENT_TYPE, content_type.unwrap());
23 }
24 let mut resp = request_builder.body(param).send().await.map_err(|err| {
26 let msg = format!("http connect error! host={}, err={}", url, err);
27 log::error!("{}", msg.as_str());
28 HttpError::new(ErrorCode::ConnectFailed, msg)
29 })?;
30
31 let header = resp.headers().get(CONTENT_TYPE);
32 let header = if header.is_some() {
33 Some(header.unwrap().to_str().map_err(|err| {
34 let msg = format!("invalid content-type {}", err);
35 log::error!("{}", msg.as_str());
36 HttpError::new(ErrorCode::InvalidParam, msg)
37 })?.to_string())
38 } else {
39 None
40 };
41 let data = resp.bytes().await.map_err(|err| {
42 let msg = format!("recv body error! err={}", err);
43 log::error!("{}", msg.as_str());
44 HttpError::new(ErrorCode::InvalidData, msg)
45 })?;
46 Ok((data.to_vec(), header))
47}
48
49pub async fn http_post_request2<T: for<'de> Deserialize<'de>>(url: &str, param: Vec<u8>, content_type: Option<&str>) -> HttpResult<T> {
50 let mut request_builder = reqwest::Client::builder().no_proxy().build().unwrap().post(url);
51 if content_type.is_some() {
52 request_builder = request_builder.header(CONTENT_TYPE, content_type.unwrap());
53 }
54 let mut resp = request_builder.body(param).send().await.map_err(|err| {
56 let msg = format!("http connect error! host={}, err={}", url, err);
57 log::error!("{}", msg.as_str());
58 HttpError::new(ErrorCode::ConnectFailed, msg)
59 })?;
60
61 let data = resp.json().await.map_err(|err| {
62 let msg = format!("recv body error! err={}", err);
63 log::error!("{}", msg.as_str());
64 HttpError::new(ErrorCode::InvalidData, msg)
65 })?;
66 Ok(data)
67}
68
69pub async fn http_post_request3<T: for<'de> Deserialize<'de>, P: Serialize>(url: &str, param: &P) -> HttpResult<T> {
70 let mut resp = reqwest::Client::builder().no_proxy().build().unwrap().post(url).json(param).send().await.map_err(|err| {
71 let msg = format!("http connect error! host={}, err={}", url, err);
72 log::error!("{}", msg.as_str());
73 HttpError::new(ErrorCode::ConnectFailed, msg)
74 })?;
75
76 resp.json().await.map_err(|err| {
77 let msg = format!("recv error! err={}", err);
78 log::error!("{}", msg.as_str());
79 HttpError::new(ErrorCode::InvalidData, msg)
80 })
81}
82
83pub async fn http_get_request2<T: for<'de> Deserialize<'de>>(url: &str) -> HttpResult<T> {
84 let resp = reqwest::Client::builder().no_proxy().build().unwrap().get(url).send().await.map_err(|err| {
85 let msg = format!("http connect error! host={}, err={}", url, err);
86 log::error!("{}", msg.as_str());
87 HttpError::new(ErrorCode::ConnectFailed, msg)
88 })?;
89
90 resp.json().await.map_err(|err| {
91 let msg = format!("recv error! err={}", err);
92 log::error!("{}", msg.as_str());
93 HttpError::new(ErrorCode::InvalidData, msg)
94 })
95}
96
97
98pub async fn http_get_request(url: &str) -> HttpResult<(Vec<u8>, Option<String>)> {
99 let resp = reqwest::Client::builder().no_proxy().build().unwrap().get(url).send().await.map_err(|err| {
100 let msg = format!("http connect error! host={}, err={}", url, err);
101 log::error!("{}", msg.as_str());
102 HttpError::new(ErrorCode::ConnectFailed, msg)
103 })?;
104
105 let header = resp.headers().get(CONTENT_TYPE);
106 let header = if header.is_some() {
107 Some(header.unwrap().to_str().map_err(|err| {
108 let msg = format!("invalid content-type {}", err);
109 log::error!("{}", msg.as_str());
110 HttpError::new(ErrorCode::InvalidParam, msg)
111 })?.to_string())
112 } else {
113 None
114 };
115 let data = resp.bytes().await.map_err(|err| {
116 let msg = format!("recv body error! err={}", err);
117 log::error!("{}", msg.as_str());
118 HttpError::new(ErrorCode::InvalidData, msg)
119 })?;
120 Ok((data.to_vec(), header))
121}
122
123pub async fn http_get_request3(url: &str) -> HttpResult<Response> {
124 reqwest::Client::builder().no_proxy().build().unwrap().get(url).send().await.map_err(|err| {
125 let msg = format!("http connect error! host={}, err={}", url, err);
126 log::error!("{}", msg.as_str());
127 HttpError::new(ErrorCode::ConnectFailed, msg)
128 })
129}
130
131pub async fn http_request(req: Request) -> HttpResult<Response> {
132 let url = req.url().to_string();
133 reqwest::Client::builder().no_proxy().build().unwrap().execute(req).await.map_err(|err| {
134 let msg = format!("http connect error! url={} err={}", url, err);
135 log::error!("{}", msg.as_str());
136 HttpError::new(ErrorCode::ConnectFailed, msg)
137 })
138}
139
140pub async fn http_post_json(url: &str, param: JsonValue) -> HttpResult<JsonValue> {
141 let resp = reqwest::Client::builder().no_proxy().build().unwrap()
142 .post(url)
143 .header(CONTENT_TYPE, "application/json")
144 .body(param.to_string())
145 .send().await.map_err(|err| {
146 let msg = format!("http connect error! url={} err={}", url, err);
147 log::error!("{}", msg.as_str());
148 HttpError::new(ErrorCode::ConnectFailed, msg)
149 })?;
150
151 let resp_str = resp.text().await.map_err(|err| {
152 let msg = format!("recv error! err={}", err);
153 log::error!("{}", msg.as_str());
154 HttpError::new(ErrorCode::InvalidData, msg)
155 })?;
156 json::parse(resp_str.as_str()).map_err(|err| {
157 let msg = format!("parse {} error! err={}", resp_str.as_str(), err);
158 log::error!("{}", msg.as_str());
159 HttpError::new(ErrorCode::InvalidData, msg)
160 })
161}
162
163
164pub async fn http_post_json2<T: for<'de> Deserialize<'de>>(url: &str, param: JsonValue) -> HttpResult<T> {
165 let resp = reqwest::Client::builder().no_proxy().build().unwrap().post(url)
166 .header(CONTENT_TYPE, "application/json")
167 .body(param.to_string())
168 .send().await.map_err(|err| {
169 let msg = format!("http connect error! url={} err={}", url, err);
170 log::error!("{}", msg.as_str());
171 HttpError::new(ErrorCode::ConnectFailed, msg)
172 })?;
173
174 resp.json().await.map_err(|err| {
175 let msg = format!("recv error! err={}", err);
176 log::error!("{}", msg.as_str());
177 HttpError::new(ErrorCode::InvalidData, msg)
178 })
179}
180
181#[derive(Clone)]
182pub struct HttpClient {
183 client: reqwest::Client,
184 base_url: Option<String>,
185}
186
187impl Debug for HttpClient {
188 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
189 write!(f, "HttpClient")
190 }
191}
192
193impl HttpClient {
194 pub fn new(max_connections: usize, base_url: Option<&str>) -> Self {
195 let client = reqwest::ClientBuilder::new()
196 .connect_timeout(Duration::from_secs(30))
197 .http2_keep_alive_while_idle(true)
198 .pool_max_idle_per_host(max_connections)
199 .no_proxy()
200 .build().unwrap();
201
202 let base_url = if base_url.is_some() {
203 let base_url = base_url.unwrap();
204 let base_url = if base_url.ends_with("/") {
205 base_url.to_string()
206 } else {
207 format!("{}/", base_url)
208 };
209 Some(base_url)
210 } else {
211 base_url.map(|v| v.to_string())
212 };
213
214 Self {
215 client,
216 base_url,
217 }
218 }
219
220 pub fn new_with_no_cert_verify(max_connections: usize, base_url: Option<&str>) -> Self {
221 let client = reqwest::ClientBuilder::new()
222 .connect_timeout(Duration::from_secs(30))
223 .http2_keep_alive_while_idle(true)
224 .use_rustls_tls()
225 .pool_max_idle_per_host(max_connections)
226 .danger_accept_invalid_certs(true)
227 .no_proxy()
228 .build().unwrap();
229
230 let base_url = if base_url.is_some() {
231 let base_url = base_url.unwrap();
232 let base_url = if base_url.ends_with("/") {
233 base_url.to_string()
234 } else {
235 format!("{}/", base_url)
236 };
237 Some(base_url)
238 } else {
239 base_url.map(|v| v.to_string())
240 };
241
242 Self {
243 client,
244 base_url,
245 }
246 }
247
248 fn get_url(&self, uri: &str) -> String {
249 if self.base_url.is_some() {
250 let base_url = self.base_url.as_ref().unwrap().as_str();
251 if base_url.ends_with("/") {
252 if uri.starts_with("/") {
253 format!("{}{}", base_url, &uri[1..])
254 } else {
255 format!("{}{}", base_url, uri)
256 }
257 } else {
258 if uri.starts_with("/") {
259 format!("{}{}", base_url, uri)
260 } else {
261 format!("{}/{}", base_url, uri)
262 }
263 }
264 } else {
265 uri.to_string()
266 }
267 }
268
269 pub async fn get_json<T: for<'de> Deserialize<'de>>(&self, uri: &str) -> HttpResult<T> {
270 let mut resp = self.client.get(self.get_url(uri).as_str()).send().await.map_err(|err| {
271 let msg = format!("http connect error! url={}, err={}", self.get_url(uri), err);
272 log::error!("{}", msg.as_str());
273 HttpError::new(ErrorCode::ConnectFailed, msg)
274 })?;
275
276 resp.json().await.map_err(|err| {
277 let msg = format!("recv error! err={}", err);
278 log::error!("{}", msg.as_str());
279 HttpError::new(ErrorCode::InvalidData, msg)
280 })
281 }
282
283 pub async fn get(&self, uri: &str) -> HttpResult<(Vec<u8>, Option<String>)> {
284 let mut resp = self.client.get(self.get_url(uri).as_str()).send().await.map_err(|err| {
285 let msg = format!("http connect error! url={}, err={}", self.get_url(uri), err);
286 log::error!("{}", msg.as_str());
287 HttpError::new(ErrorCode::ConnectFailed, msg)
288 })?;
289
290 let header = resp.headers().get(CONTENT_TYPE);
291 let header = if header.is_some() {
292 Some(header.unwrap().to_str().map_err(|err| {
293 let msg = format!("invalid content-type {}", err);
294 log::error!("{}", msg.as_str());
295 HttpError::new(ErrorCode::InvalidParam, msg)
296 })?.to_string())
297 } else {
298 None
299 };
300 let data = resp.bytes().await.map_err(|err| {
301 let msg = format!("recv body error! err={}", err);
302 log::error!("{}", msg.as_str());
303 HttpError::new(ErrorCode::InvalidData, msg)
304 })?;
305 Ok((data.to_vec(), header))
306 }
307
308 pub async fn post_json<T: for<'de> Deserialize<'de>, P: Serialize>(&self, uri: &str, param: &P) -> HttpResult<T> {
309 let mut resp = self.client.post(self.get_url(uri)).json(param).send().await.map_err(|err| {
310 let msg = format!("http connect error! url={}, err={}", self.get_url(uri), err);
311 log::error!("{}", msg.as_str());
312 HttpError::new(ErrorCode::ConnectFailed, msg)
313 })?;
314
315 resp.json().await.map_err(|err| {
316 let msg = format!("recv error! err={}", err);
317 log::error!("{}", msg.as_str());
318 HttpError::new(ErrorCode::InvalidData, msg)
319 })
320 }
321
322 pub async fn post(&self, uri: &str, param: Vec<u8>, content_type: Option<&str>) -> HttpResult<(Vec<u8>, Option<String>)> {
323 let mut request_builder = self.client.post(self.get_url(uri));
324 if content_type.is_some() {
325 request_builder = request_builder.header(CONTENT_TYPE, content_type.unwrap());
326 }
327 let mut resp = request_builder.body(param).send().await.map_err(|err| {
329 let msg = format!("http connect error! host={}, err={}", self.get_url(uri), err);
330 log::error!("{}", msg.as_str());
331 HttpError::new(ErrorCode::ConnectFailed, msg)
332 })?;
333
334 let header = resp.headers().get(CONTENT_TYPE);
335 let header = if header.is_some() {
336 Some(header.unwrap().to_str().map_err(|err| {
337 let msg = format!("invalid content-type {}", err);
338 log::error!("{}", msg.as_str());
339 HttpError::new(ErrorCode::InvalidParam, msg)
340 })?.to_string())
341 } else {
342 None
343 };
344
345 let data = resp.bytes().await.map_err(|err| {
346 let msg = format!("recv body error! err={}", err);
347 log::error!("{}", msg.as_str());
348 HttpError::new(ErrorCode::InvalidData, msg)
349 })?;
350 Ok((data.to_vec(), header))
351 }
352
353 pub async fn execute(&self, req: Request) -> HttpResult<Response> {
354 let url = req.url().to_string();
355 self.client.execute(req).await.map_err(|err| {
356 let msg = format!("http connect error! url={} err={}", url, err);
357 log::error!("{}", msg.as_str());
358 HttpError::new(ErrorCode::ConnectFailed, msg)
359 })
360 }
361}
362
363pub struct HttpClientBuilder {
364 base_url: Option<String>,
365 builder: ClientBuilder,
366 headers: HeaderMap,
367}
368
369impl Default for HttpClientBuilder {
370 fn default() -> Self {
371 Self {
372 base_url: None,
373 builder: ClientBuilder::new(),
374 headers: Default::default(),
375 }
376 }
377}
378
379impl HttpClientBuilder {
380 pub fn set_base_url(mut self, base_url: &str) -> Self {
381 let base_url = if base_url.ends_with("/") {
382 base_url.to_string()
383 } else {
384 format!("{}/", base_url)
385 };
386 self.base_url = Some(base_url);
387 self
388 }
389 pub fn add_header(
390 mut self,
391 name: impl Into<HeaderName>,
392 value: impl Into<HeaderValue>,
393 ) -> HttpResult<Self> {
394 self.headers
395 .insert(name.into(), value.into());
396 Ok(self)
397 }
398
399 pub fn set_http_keep_alive(mut self, keep_alive: bool) -> Self {
400 self.builder = self.builder.http2_keep_alive_while_idle(keep_alive);
401 self
402 }
403
404 pub fn set_tcp_no_delay(mut self, no_delay: bool) -> Self {
405 self.builder = self.builder.tcp_nodelay(no_delay);
406 self
407 }
408
409 pub fn set_timeout(mut self, timeout: Duration) -> Self {
410 self.builder = self.builder.connect_timeout(timeout);
411 self
412 }
413
414 pub fn set_max_connections_per_host(mut self, max_connections_per_host: usize) -> Self {
415 self.builder = self.builder.pool_max_idle_per_host(max_connections_per_host);
416 self
417 }
418
419 pub fn set_verify_tls(mut self, verify_tls: bool) -> Self {
420 self.builder = self.builder.danger_accept_invalid_certs(!verify_tls);
421 self
422 }
423
424 pub fn set_auto_sys_proxy(mut self, proxy: bool) -> Self {
425 if !proxy {
426 self.builder = self.builder.no_proxy();
427 }
428 self
429 }
430
431 pub fn add_root_certificate(mut self, cert: Certificate) -> Self {
432 self.builder = self.builder.add_root_certificate(cert);
433 self
434 }
435
436 pub fn tls_built_in_root_certs(mut self, tls_built_in_root_certs: bool) -> Self {
437 self.builder = self.builder.tls_built_in_root_certs(tls_built_in_root_certs);
438 self
439 }
440
441 pub fn identity(mut self, identity: Identity) -> Self {
442 self.builder = self.builder.identity(identity);
443 self
444 }
445
446 pub fn tls_sni(mut self, tls_sni: bool) -> Self {
447 self.builder = self.builder.tls_sni(tls_sni);
448 self
449 }
450
451 pub fn min_tls_version(mut self, version: tls::Version) -> Self {
452 self.builder = self.builder.min_tls_version(version);
453 self
454 }
455
456 pub fn max_tls_version(mut self, version: tls::Version) -> Self {
457 self.builder = self.builder.max_tls_version(version);
458 self
459 }
460
461 pub fn https_only(mut self, enabled: bool) -> Self {
462 self.builder = self.builder.https_only(enabled);
463 self
464 }
465
466 pub fn resolve(mut self, domain: &str, addr: SocketAddr) -> Self {
467 self.builder = self.builder.resolve(domain, addr);
468 self
469 }
470
471 pub fn resolve_to_addrs(mut self, domain: &str, addrs: &[SocketAddr]) -> Self {
472 self.builder = self.builder.resolve_to_addrs(domain, addrs);
473 self
474 }
475
476 pub fn dns_resolver<R: Resolve + 'static>(mut self, resolver: Arc<R>) -> Self {
477 self.builder = self.builder.dns_resolver(resolver);
478 self
479 }
480
481 pub fn proxy(mut self, proxy: Proxy) -> Self {
482 self.builder = self.builder.proxy(proxy);
483 self
484 }
485
486 pub fn build(mut self) -> HttpClient {
487 let mut config = self.builder.default_headers(self.headers);
488
489 HttpClient {
490 client: config.build().unwrap(),
491 base_url: self.base_url,
492 }
493 }
494}