1use std::marker::PhantomData;
2use std::ops::Deref;
3
4use mlua::{
5 FromLua, IntoLua, Lua, ObjectLike, Result, String as LuaString, Table, TablePairs, Value,
6};
7
8#[derive(Clone)]
10pub struct Http(Table);
11
12#[derive(Clone)]
13pub struct Headers(Table);
14
15impl Http {
16 #[inline]
18 pub fn req_get_headers(&self) -> Result<Headers> {
19 self.0.call_method("req_get_headers", ())
20 }
21
22 #[inline]
24 pub fn res_get_headers(&self) -> Result<Headers> {
25 self.0.call_method("res_get_headers", ())
26 }
27
28 #[inline]
30 pub fn req_add_header(&self, name: &str, value: impl IntoLua) -> Result<()> {
31 self.0.call_method("req_add_header", (name, value))
32 }
33
34 #[inline]
36 pub fn res_add_header(&self, name: &str, value: impl IntoLua) -> Result<()> {
37 self.0.call_method("res_add_header", (name, value))
38 }
39
40 #[inline]
42 pub fn req_del_header(&self, name: &str) -> Result<()> {
43 self.0.call_method("req_del_header", name)
44 }
45
46 #[inline]
48 pub fn res_del_header(&self, name: &str) -> Result<()> {
49 self.0.call_method("res_del_header", name)
50 }
51
52 #[inline]
54 pub fn req_set_header(&self, name: &str, value: impl IntoLua) -> Result<()> {
55 self.0.call_method("req_set_header", (name, value))
56 }
57
58 #[inline]
60 pub fn res_set_header(&self, name: &str, value: impl IntoLua) -> Result<()> {
61 self.0.call_method("res_set_header", (name, value))
62 }
63
64 #[inline]
69 pub fn req_rep_header(&self, name: &str, regex: &str, replace: &str) -> Result<()> {
70 self.0.call_method("req_rep_header", (name, regex, replace))
71 }
72
73 #[inline]
78 pub fn res_rep_header(&self, name: &str, regex: &str, replace: &str) -> Result<()> {
79 self.0.call_method("res_rep_header", (name, regex, replace))
80 }
81
82 #[inline]
84 pub fn req_set_method(&self, method: &str) -> Result<()> {
85 self.0.call_method("req_set_method", method)
86 }
87
88 #[inline]
90 pub fn req_set_path(&self, path: &str) -> Result<()> {
91 self.0.call_method("req_set_path", path)
92 }
93
94 #[inline]
97 pub fn req_set_query(&self, query: &str) -> Result<()> {
98 self.0.call_method("req_set_query", query)
99 }
100
101 #[inline]
103 pub fn req_set_uri(&self, uri: &str) -> Result<()> {
104 self.0.call_method("req_set_uri", uri)
105 }
106
107 #[inline]
110 pub fn res_set_status(&self, status: u16, reason: Option<&str>) -> Result<()> {
111 self.0.call_method("res_set_status", (status, reason))
112 }
113}
114
115impl Deref for Http {
116 type Target = Table;
117
118 #[inline]
119 fn deref(&self) -> &Self::Target {
120 &self.0
121 }
122}
123
124impl FromLua for Http {
125 #[inline]
126 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
127 Ok(Http(Table::from_lua(value, lua)?))
128 }
129}
130
131impl Headers {
132 #[inline]
133 pub fn pairs<V: FromLua>(&self) -> HeaderPairs<'_, V> {
134 HeaderPairs {
135 pairs: self.0.pairs(),
136 phantom: PhantomData,
137 }
138 }
139
140 #[inline]
142 pub fn get<V: FromLua>(&self, name: &str) -> Result<Vec<V>> {
143 let name = name.to_ascii_lowercase();
144 let mut result = Vec::new();
145 if let Some(values) = self.0.get::<Option<Table>>(name)? {
146 let mut pairs = values.pairs::<i32, V>().collect::<Result<Vec<_>>>()?;
147 pairs.sort_by_key(|x| x.0);
148 result = pairs.into_iter().map(|(_, v)| v).collect();
149 }
150 Ok(result)
151 }
152
153 #[inline]
155 pub fn get_first<V: FromLua>(&self, name: &str) -> Result<Option<V>> {
156 let name = name.to_ascii_lowercase();
157 if let Some(values) = self.0.get::<Option<Table>>(name)? {
158 return values.get(0); }
160 Ok(None)
161 }
162}
163
164impl Deref for Headers {
165 type Target = Table;
166
167 #[inline]
168 fn deref(&self) -> &Self::Target {
169 &self.0
170 }
171}
172
173impl FromLua for Headers {
174 #[inline]
175 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
176 Ok(Headers(Table::from_lua(value, lua)?))
177 }
178}
179
180pub struct HeaderPairs<'a, V: FromLua> {
181 pairs: TablePairs<'a, LuaString, Table>,
182 phantom: PhantomData<V>,
183}
184
185impl<V: FromLua> Iterator for HeaderPairs<'_, V> {
186 type Item = Result<(String, Vec<V>)>;
187
188 fn next(&mut self) -> Option<Self::Item> {
189 match self.pairs.next() {
190 Some(Ok(item)) => {
191 let name = item.0.to_string_lossy();
192 let pairs = item.1.pairs::<i32, V>().collect::<Result<Vec<_>>>();
193 match pairs {
194 Ok(mut pairs) => {
195 pairs.sort_by_key(|x| x.0);
196 Some(Ok((name, pairs.into_iter().map(|(_, v)| v).collect())))
197 }
198 Err(e) => Some(Err(e)),
199 }
200 }
201 Some(Err(e)) => Some(Err(e)),
202 None => None,
203 }
204 }
205}