1use std::collections::HashMap;
2
3use bytes::Bytes;
4use http_body_util::BodyExt;
5use hyper::header::HeaderName;
6use hyper::{Request, Uri, Version, body::Incoming, header::HeaderValue};
7use serde::de::DeserializeOwned;
8use url::form_urlencoded;
9
10pub struct RequestBody {
11 inner: Request<Incoming>,
12 params: HashMap<String, String>,
13}
14
15#[allow(dead_code)]
16impl RequestBody {
17 pub fn new(req: Request<Incoming>) -> Self {
18 Self {
19 inner: req,
20 params: HashMap::new(),
21 }
22 }
23
24 pub fn params(&self) -> &HashMap<String, String> {
25 &self.params
26 }
27
28 pub(crate) fn set_params(&mut self, params: HashMap<String, String>) {
29 self.params = params;
30 }
31
32 pub fn method(&self) -> &hyper::Method {
33 self.inner.method()
34 }
35
36 pub fn path(&self) -> &str {
37 self.inner.uri().path()
38 }
39
40 pub fn headers(&self) -> &hyper::HeaderMap {
41 self.inner.headers()
42 }
43
44 pub fn set_headers(&mut self, key: &str, value: &str) {
45 let key = HeaderName::from_bytes(key.as_bytes()).expect("Invalid header name");
46 let value = HeaderValue::from_str(value).expect("Invalid header value");
47
48 self.inner.headers_mut().insert(key, value);
49 }
50
51 pub fn get_headers(&mut self, key: &str) -> Option<&HeaderValue> {
52 self.inner.headers().get(key)
53 }
54
55 pub fn uri(&self) -> &Uri {
56 self.inner.uri()
57 }
58
59 pub fn version(&self) -> Version {
60 self.inner.version()
61 }
62
63 pub fn query(&self) -> HashMap<String, String> {
64 self.inner
65 .uri()
66 .query()
67 .map(|q| {
68 form_urlencoded::parse(q.as_bytes())
69 .into_owned()
70 .collect::<HashMap<String, String>>()
71 })
72 .unwrap_or_default()
73 }
74
75 pub fn query_param(&self, key: &str) -> Option<String> {
76 let query_params = self.query();
77 query_params.get(key).cloned()
78 }
79
80 pub async fn bytes(self) -> Result<Bytes, hyper::Error> {
81 let (_, body) = self.inner.into_parts();
82 let collected = body.collect().await?;
83 Ok(collected.to_bytes())
84 }
85
86 pub async fn text(self) -> Result<String, Box<dyn std::error::Error>> {
87 let bytes = self.bytes().await?;
88 let text = String::from_utf8(bytes.to_vec())?;
89 Ok(text)
90 }
91
92 pub async fn json<T: DeserializeOwned>(self) -> Result<T, Box<dyn std::error::Error>> {
93 let bytes = self.bytes().await?;
94 let value = serde_json::from_slice(&bytes)?;
95 Ok(value)
96 }
97
98 pub fn get_cookie(&self, name: &str) -> Option<String> {
99 self.inner
100 .headers()
101 .get(hyper::header::COOKIE)?
102 .to_str()
103 .ok()
104 .and_then(|cookie_header| {
105 cookie_header.split(';').map(|s| s.trim()).find_map(|pair| {
106 let mut parts = pair.splitn(2, '=');
107 let key = parts.next()?;
108 let value = parts.next()?;
109 if key == name {
110 Some(value.to_string())
111 } else {
112 None
113 }
114 })
115 })
116 }
117}