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>;
28pub 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}
50pub 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 ¶m.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) = ¶m.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}