httpray/
lib.rs

1pub mod ram;
2mod request;
3pub mod rest_api;
4
5pub use request::{request, RequestError};
6
7use bytes::{BufMut, Bytes, BytesMut};
8use http_body_util::BodyExt;
9use hyper::body::Incoming;
10use hyper::http::request::Builder;
11use hyper::Request;
12use hyper::{header::HeaderValue, HeaderMap, Response, StatusCode};
13use hyper_tls::{native_tls, HttpsConnector};
14use hyper_util::client::legacy::connect::HttpConnector;
15use hyper_util::client::legacy::Client;
16use hyper_util::rt::TokioExecutor;
17use std::error::Error;
18use std::net::IpAddr;
19use tracing::error;
20use url::Url;
21use crate::ram::RestApiMethod;
22
23const RESPONSE_LEN_LIMIT: usize = 16384000;
24
25pub type HyperClient = Client<HttpsConnector<HttpConnector>, String>;
26#[allow(dead_code)]
27pub type HyperClientUnsecured = Client<HttpConnector, String>;
28// pub type HyperClientProxy = Client<ProxyConnector<HttpConnector>, String>;
29
30pub fn create_hyper(ip: Option<IpAddr>) -> HyperClient {
31    match ip {
32        None => {
33            let https = HttpsConnector::new();
34            Client::builder(TokioExecutor::new()).build::<_, String>(https)
35        }
36        Some(ip) => {
37            let https = native_tls::TlsConnector::new().map_or_else(
38                |e| panic!("HttpsConnector::new() failure: {}", e),
39                |tls| {
40                    let mut http = HttpConnector::new();
41                    http.set_local_address(Some(ip));
42                    http.enforce_http(false);
43                    HttpsConnector::from((http, tls.into()))
44                },
45            );
46            Client::builder(TokioExecutor::new()).build::<_, String>(https)
47        }
48    }
49}
50// pub fn create_hyper_proxy(proxy: &proxy::Model) -> HyperClientProxy {
51//     let proxy_connector = {
52//         let proxy_uri = format!("http://{}:3128", proxy.ip).parse().unwrap();
53//         let proxy = Proxy::new(Intercept::All, proxy_uri);
54//         let connector = HttpConnector::new();
55//         let proxy_connector = ProxyConnector::from_proxy(connector, proxy).unwrap();
56//         proxy_connector
57//     };
58//     Client::builder(TokioExecutor::new()).build(proxy_connector)
59// }
60
61pub fn create_request_builder() -> Builder {
62    Request::builder().header(
63        "User-Agent",
64        format!("GhostScope/{}", env!("CARGO_PKG_VERSION")),
65    )
66}
67
68pub fn compile_uri<R, BRE>(ram: &RestApiMethod<R, BRE>) -> Result<Url, String> {
69    let mut url = ram.url.to_string();
70    for param in &ram.route_params {
71        let val = match &param.value {
72            Some(x) => x,
73            None => {
74                return Err(format!(
75                    "compile_uri Required route param {} not set.",
76                    param.key
77                ));
78            }
79        };
80        let key = format!("{{{}}}", param.key);
81        url = url.replace(&key, val);
82    }
83    let mut res = Url::parse(format!("{}{}", ram.base_url, url).as_str()).unwrap();
84    for param in &ram.query_params.items {
85        if let Some(value) = &param.value {
86            res.query_pairs_mut()
87                .append_pair(param.key, &value.to_string());
88        } else if param.is_required {
89            return Err(format!("compile_uri Required param {} not set.", param.key));
90        }
91    }
92    Ok(res)
93}
94
95pub async fn response_into_parts(
96    response: Response<Incoming>,
97) -> Result<(StatusCode, HeaderMap<HeaderValue>, Bytes), Box<dyn Error + Send + Sync>> {
98    let (parts, body) = response.into_parts();
99    let mut limited = http_body_util::Limited::new(body, RESPONSE_LEN_LIMIT);
100    let mut full = BytesMut::new();
101    while let Some(frame_recv) = limited.frame().await {
102        match frame_recv {
103            Ok(frame) => {
104                let data = frame.into_data().unwrap();
105                full.put(data);
106            }
107            Err(e) => return Err(e),
108        }
109    }
110    Ok((parts.status, parts.headers, full.into()))
111}
112
113pub fn print_request_error(error: &str, uri: &str, request: &Request<String>) {
114    error!("[Send request error] {}", error);
115    error!("  URL: {}", uri);
116    error!("  Method: {}", request.method());
117    error!("  Headers: {:?}", request.headers());
118    error!("  Body: {:?}", request.body());
119}