awesome_operates/proxy.rs
1// use std::time::Duration;
2//
3// use async_trait::async_trait;
4// use axum::body::Body;
5// use axum::extract::Request;
6// use axum::http;
7// use axum::response::{IntoResponse, Response};
8// use http::uri::{Parts, Scheme};
9// use http::Uri;
10// use snafu::ResultExt;
11// use tower::make::Shared;
12//
13// use crate::error::{RequestBodyReadSnafu, RequestProxySnafu, Result, UriFromPartsSnafu};
14//
15// #[async_trait]
16// pub trait HttpProxy: 'static {
17// fn listen_addr() -> &'static str;
18//
19// fn target_addr() -> String;
20//
21// fn proxy_timeout() -> u64 {
22// 10
23// }
24//
25// fn default_schema() -> Scheme {
26// Scheme::HTTP
27// }
28//
29// async fn service_proxy(req: Request<hyper::body::Incoming>) -> Result<Response> {
30// let uri = req.uri();
31//
32// let mut parts = Parts::default();
33// parts.scheme = Some(Self::default_schema());
34// parts.authority = Some(Self::target_addr().parse().unwrap());
35// parts.path_and_query = uri.path_and_query().cloned();
36// tracing::debug!("receive proxy: {parts:?} headers: {:?}", req.headers());
37// let changed_uri = Uri::from_parts(parts).context(UriFromPartsSnafu)?;
38//
39// let client = reqwest::Client::new();
40// let resp = client
41// .request(req.method().clone(), changed_uri.to_string())
42// .headers(req.headers().clone())
43// .body(req.into_body())
44// .timeout(Duration::from_secs(Self::proxy_timeout()))
45// .send()
46// .await
47// .context(RequestProxySnafu)?;
48//
49// let status_code = resp.status();
50// let headers = resp.headers().clone();
51// tracing::debug!("proxy result {changed_uri:?} with resp: {status_code} {headers:?}");
52// let body = resp.bytes().await.context(RequestBodyReadSnafu)?;
53// let mut res = Body::from(body).into_response();
54// *res.status_mut() = status_code;
55// *res.headers_mut() = headers;
56// Ok(res)
57// }
58//
59// async fn proxy_server() {
60// tracing::info!("listening on {}", Self::listen_addr());
61// let service = tower::service_fn(Self::service_proxy);
62// hyper::Server::bind(&Self::listen_addr().parse().unwrap())
63// .http1_preserve_header_case(true)
64// .http1_title_case_headers(true)
65// .serve(Shared::new(service))
66// .await
67// .unwrap();
68// }
69// }