1use bytes::Bytes;
2use http::{HeaderMap, HeaderName, HeaderValue};
3use parking_lot::RwLock;
4use std::collections::HashMap;
5use std::sync::Arc;
6use wasmer::Memory;
7
8#[derive(Clone, Debug)]
9pub struct ResponseState {
10 headers: HeaderMap,
11 status: u16,
12 status_overridden: bool,
13}
14
15impl ResponseState {
16 pub fn with_default_status(status: u16) -> Self {
17 Self::from_parts(HeaderMap::new(), status, false)
18 }
19
20 pub fn from_parts(headers: HeaderMap, status: u16, status_overridden: bool) -> Self {
21 Self {
22 headers,
23 status,
24 status_overridden,
25 }
26 }
27
28 pub fn from_hash_map(
29 headers: HashMap<String, String>,
30 status: u16,
31 status_overridden: bool,
32 ) -> Self {
33 let map = header_map_from_hashmap(headers);
34 Self::from_parts(map, status, status_overridden)
35 }
36
37 pub fn headers(&self) -> &HeaderMap {
38 &self.headers
39 }
40
41 pub fn headers_mut(&mut self) -> &mut HeaderMap {
42 &mut self.headers
43 }
44
45 pub fn insert_header(&mut self, name: HeaderName, value: HeaderValue) {
46 self.headers.insert(name, value);
47 }
48
49 pub fn status(&self) -> u16 {
50 self.status
51 }
52
53 pub fn set_status(&mut self, status: u16) {
54 self.status = status;
55 self.status_overridden = true;
56 }
57
58 pub fn status_override(&self) -> Option<u16> {
59 self.status_overridden.then_some(self.status)
60 }
61}
62
63impl Default for ResponseState {
64 fn default() -> Self {
65 Self::with_default_status(0)
66 }
67}
68
69#[derive(Debug)]
70struct QueryStore {
71 entries: HashMap<String, Arc<Vec<String>>>,
72}
73
74impl QueryStore {
75 fn new(entries: HashMap<String, Vec<String>>) -> Self {
76 let mut map = HashMap::with_capacity(entries.len());
77 for (key, values) in entries {
78 let normalized = key.to_ascii_lowercase();
79 map.insert(normalized, Arc::new(values));
80 }
81 Self { entries: map }
82 }
83
84 fn get_first(&self, key: &str) -> Option<String> {
85 let normalized = key.to_ascii_lowercase();
86 self.entries
87 .get(&normalized)
88 .and_then(|values| values.first().cloned())
89 }
90
91 fn to_hash_map(&self) -> HashMap<String, Vec<String>> {
92 self.entries
93 .iter()
94 .map(|(key, values)| (key.clone(), (**values).clone()))
95 .collect()
96 }
97}
98
99#[derive(Clone, Debug)]
100pub struct RequestState {
101 headers: Arc<HeaderMap>,
102 query: Arc<QueryStore>,
103 body: Option<Bytes>,
104 persistent_vars: Arc<RwLock<HashMap<String, String>>>,
105}
106
107impl RequestState {
108 pub fn new(
109 headers: HashMap<String, String>,
110 query: HashMap<String, Vec<String>>,
111 body: Option<Bytes>,
112 persistent_vars: Arc<RwLock<HashMap<String, String>>>,
113 ) -> Self {
114 let header_map = header_map_from_hashmap(headers);
115 let query_store = QueryStore::new(query);
116 Self {
117 headers: Arc::new(header_map),
118 query: Arc::new(query_store),
119 body,
120 persistent_vars,
121 }
122 }
123
124 pub fn empty() -> Self {
125 Self {
126 headers: Arc::new(HeaderMap::new()),
127 query: Arc::new(QueryStore::new(HashMap::new())),
128 body: None,
129 persistent_vars: Arc::new(RwLock::new(HashMap::new())),
130 }
131 }
132
133 pub fn headers(&self) -> &HeaderMap {
134 &self.headers
135 }
136
137 pub fn header_bytes(&self, name: &str) -> Option<Vec<u8>> {
138 let header_name = HeaderName::from_bytes(name.as_bytes()).ok()?;
139 self.headers
140 .get(&header_name)
141 .map(|value| value.as_bytes().to_vec())
142 }
143
144 pub fn query_first(&self, key: &str) -> Option<String> {
145 self.query.get_first(key)
146 }
147
148 pub fn query_entries(&self) -> HashMap<String, Vec<String>> {
149 self.query.to_hash_map()
150 }
151
152 pub fn body(&self) -> Option<&Bytes> {
153 self.body.as_ref()
154 }
155
156 pub fn set_body(&mut self, body: Option<Bytes>) {
157 self.body = body;
158 }
159
160 pub fn persistent_vars(&self) -> &Arc<RwLock<HashMap<String, String>>> {
161 &self.persistent_vars
162 }
163}
164
165impl Default for RequestState {
166 fn default() -> Self {
167 Self::empty()
168 }
169}
170
171#[derive(Clone, Default, Debug)]
172pub struct ExecutionContext {
173 memory: Option<Memory>,
174 request: RequestState,
175 response: ResponseState,
176}
177
178impl ExecutionContext {
179 pub fn new() -> Self {
180 Self::default()
181 }
182
183 pub fn with_response(response: ResponseState) -> Self {
184 Self {
185 response,
186 ..Self::default()
187 }
188 }
189
190 pub fn from_parts(
191 req_headers: HashMap<String, String>,
192 query: HashMap<String, Vec<String>>,
193 body: Option<Bytes>,
194 response: ResponseState,
195 persistent_vars: Arc<RwLock<HashMap<String, String>>>,
196 ) -> Self {
197 let request = RequestState::new(req_headers, query, body, persistent_vars);
198 Self {
199 memory: None,
200 request,
201 response,
202 }
203 }
204
205 pub fn replace_memory(&mut self, memory: Memory) {
206 self.memory.replace(memory);
207 }
208
209 pub fn memory(&self) -> &Option<Memory> {
210 &self.memory
211 }
212
213 pub fn memory_mut(&mut self) -> &mut Option<Memory> {
214 &mut self.memory
215 }
216
217 pub fn request(&self) -> &RequestState {
218 &self.request
219 }
220
221 pub fn request_mut(&mut self) -> &mut RequestState {
222 &mut self.request
223 }
224
225 pub fn response(&self) -> &ResponseState {
226 &self.response
227 }
228
229 pub fn response_mut(&mut self) -> &mut ResponseState {
230 &mut self.response
231 }
232
233 pub fn persistent_vars(&self) -> &Arc<RwLock<HashMap<String, String>>> {
234 self.request.persistent_vars()
235 }
236}
237
238pub type SharedExecutionContext = Arc<RwLock<ExecutionContext>>;
239
240fn header_map_from_hashmap(headers: HashMap<String, String>) -> HeaderMap {
241 let mut header_map = HeaderMap::with_capacity(headers.len());
242 for (key, value) in headers {
243 if let (Ok(name), Ok(val)) = (
244 HeaderName::from_bytes(key.as_bytes()),
245 HeaderValue::from_str(&value),
246 ) {
247 header_map.append(name, val);
248 }
249 }
250 header_map
251}