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