1#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
2pub struct Request {
3 pub uri: String,
4 pub method: String,
5 pub headers: Vec<(String, Vec<u8>)>,
6}
7
8impl From<hyper::http::request::Parts> for Request {
9 fn from(r: hyper::http::request::Parts) -> Self {
10 let mut headers = vec![];
11 for (k, v) in r.headers {
12 let k = match k {
13 Some(v) => v.to_string(),
14 None => continue,
15 };
16 headers.push((k, v.as_bytes().to_vec()));
17 }
18
19 Request {
20 uri: r.uri.to_string(),
21 method: r.method.to_string(),
22 headers,
23 }
24 }
25}
26
27#[derive(serde::Deserialize, serde::Serialize, Debug)]
28pub struct Response {
29 pub status: u16,
30 pub headers: Vec<(String, Vec<u8>)>,
31}
32
33pub type ProxyResponse<E = hyper::Error> =
34 hyper::Response<http_body_util::combinators::BoxBody<hyper::body::Bytes, E>>;
35pub type ProxyResult<E = hyper::Error> = eyre::Result<ProxyResponse<E>>;
36
37#[allow(dead_code)]
38pub fn server_error_<E>(s: String) -> ProxyResponse<E> {
39 bytes_to_resp(s.into_bytes(), hyper::StatusCode::INTERNAL_SERVER_ERROR)
40}
41
42#[allow(dead_code)]
43pub fn not_found_(m: String) -> ProxyResponse {
44 bytes_to_resp(m.into_bytes(), hyper::StatusCode::NOT_FOUND)
45}
46
47pub fn bad_request_<E>(m: String) -> ProxyResponse<E> {
48 bytes_to_resp(m.into_bytes(), hyper::StatusCode::BAD_REQUEST)
49}
50
51#[macro_export]
52macro_rules! server_error {
53 ($($t:tt)*) => {{
54 $crate::http::server_error_(format!($($t)*))
55 }};
56}
57
58#[macro_export]
59macro_rules! not_found {
60 ($($t:tt)*) => {{
61 $crate::http::not_found_(format!($($t)*))
62 }};
63}
64
65#[macro_export]
66macro_rules! bad_request {
67 ($($t:tt)*) => {{
68 $crate::http::bad_request_(format!($($t)*))
69 }};
70}
71
72#[allow(dead_code)]
73pub fn redirect<S: AsRef<str>>(url: S) -> ProxyResponse {
74 let mut r = bytes_to_resp(vec![], hyper::StatusCode::PERMANENT_REDIRECT);
75 *r.headers_mut().get_mut(hyper::header::LOCATION).unwrap() = url.as_ref().parse().unwrap();
76 r
77}
78
79pub fn bytes_to_resp<E>(bytes: Vec<u8>, status: hyper::StatusCode) -> ProxyResponse<E> {
80 use http_body_util::BodyExt;
81
82 let mut r = hyper::Response::new(
83 http_body_util::Full::new(hyper::body::Bytes::from(bytes))
84 .map_err(|e| match e {})
85 .boxed(),
86 );
87 *r.status_mut() = status;
88 r
89}
90
91pub fn vec_u8_to_bytes(req: hyper::Request<Vec<u8>>) -> hyper::Request<hyper::body::Bytes> {
92 let (head, body) = req.into_parts();
93 let body = hyper::body::Bytes::from(body);
94 hyper::Request::from_parts(head, body)
95}
96
97pub async fn incoming_to_bytes(
98 req: hyper::Request<hyper::body::Incoming>,
99) -> eyre::Result<hyper::Request<hyper::body::Bytes>> {
100 use http_body_util::BodyDataStream;
101 use tokio_stream::StreamExt;
102
103 let (head, body) = req.into_parts();
104 let mut stream = BodyDataStream::new(body);
105 let mut body = bytes::BytesMut::new();
106
107 while let Some(chunk) = stream.next().await {
108 body.extend_from_slice(&chunk?);
109 }
110
111 Ok(hyper::Request::from_parts(head, body.freeze()))
112}
113
114pub async fn response_to_static(
115 resp: ProxyResult,
116) -> eyre::Result<hyper::Response<std::borrow::Cow<'static, [u8]>>> {
117 use http_body_util::BodyExt;
118 let resp = resp?;
119
120 let (parts, body) = resp.into_parts();
121 let bytes = body.collect().await?.to_bytes();
122
123 let new_resp = hyper::Response::from_parts(parts, std::borrow::Cow::Owned(bytes.to_vec()));
124
125 Ok(new_resp)
126}