1use std::ops::RangeBounds;
2
3use crate::{
4 calculate_range,
5 context::BaseContext,
6 hostcalls::{self, BufferType, MapType},
7 log_concern,
8 property::envoy::Attributes,
9 Status,
10};
11
12pub trait HttpControl {
14 const TYPE: HttpType;
16
17 fn attributes(&self) -> &Attributes;
19
20 fn end_of_stream(&self) -> bool {
22 true
23 }
24
25 fn resume(&self) {
27 log_concern(Self::TYPE.resume(), Self::TYPE.call_resume())
28 }
29
30 fn reset(&self) {
32 log_concern(Self::TYPE.reset(), Self::TYPE.call_reset())
33 }
34
35 fn send_http_response(
37 &self,
38 status_code: u32,
39 headers: &[(&str, &[u8])],
40 body: Option<&[u8]>,
41 ) -> Result<(), Status> {
42 hostcalls::send_http_response(status_code, headers, body)
43 }
44
45 fn done(&self) {
47 log_concern("trigger-done", hostcalls::done());
48 }
49}
50
51pub trait HttpHeaderControl: HttpControl {
53 const HEADER_TYPE: HeaderType;
55
56 fn header_count(&self) -> usize;
58
59 fn all(&self) -> Vec<(String, Vec<u8>)> {
61 log_concern(
62 Self::HEADER_TYPE.all(),
63 hostcalls::get_map(Self::HEADER_TYPE.map()),
64 )
65 .unwrap_or_default()
66 }
67
68 fn get(&self, name: impl AsRef<str>) -> Option<Vec<u8>> {
70 log_concern(
71 Self::HEADER_TYPE.get(),
72 hostcalls::get_map_value(Self::HEADER_TYPE.map(), name.as_ref()),
73 )
74 }
75
76 fn set(&self, name: impl AsRef<str>, value: impl AsRef<[u8]>) {
78 log_concern(
79 Self::HEADER_TYPE.set(),
80 hostcalls::set_map_value(Self::HEADER_TYPE.map(), name.as_ref(), Some(value.as_ref())),
81 );
82 }
83
84 fn set_all(&self, values: &[(&str, &[u8])]) {
86 log_concern(
87 Self::HEADER_TYPE.set_all(),
88 hostcalls::set_map(Self::HEADER_TYPE.map(), values),
89 );
90 }
91
92 fn add(&self, name: impl AsRef<str>, value: impl AsRef<[u8]>) {
94 log_concern(
95 Self::HEADER_TYPE.add(),
96 hostcalls::add_map_value(Self::HEADER_TYPE.map(), name.as_ref(), value.as_ref()),
97 );
98 }
99
100 fn remove(&self, name: impl AsRef<str>) {
102 log_concern(
103 Self::HEADER_TYPE.remove(),
104 hostcalls::set_map_value(Self::HEADER_TYPE.map(), name.as_ref(), None),
105 );
106 }
107}
108
109pub trait HttpBodyControl: HttpControl {
111 fn body_size(&self) -> usize;
113
114 fn get(&self, range: impl RangeBounds<usize>) -> Option<Vec<u8>> {
116 let (start, size) = calculate_range(range, self.body_size());
117 log_concern(
118 Self::TYPE.get(),
119 hostcalls::get_buffer(Self::TYPE.buffer(), start, size),
120 )
121 }
122
123 fn set(&self, range: impl RangeBounds<usize>, value: &[u8]) {
125 let (start, size) = calculate_range(range, self.body_size());
126 log_concern(
127 Self::TYPE.set(),
128 hostcalls::set_buffer(Self::TYPE.buffer(), start, size, value),
129 );
130 }
131
132 fn all(&self) -> Option<Vec<u8>> {
134 self.get(..)
135 }
136
137 fn replace(&self, value: &[u8]) {
139 self.set(.., value);
140 }
141
142 fn clear(&self) {
144 self.replace(&[]);
145 }
146}
147
148pub enum HeaderType {
150 RequestHeaders,
151 RequestTrailers,
152 ResponseHeaders,
153 ResponseTrailers,
154}
155
156impl HeaderType {
157 const fn all(&self) -> &'static str {
158 match self {
159 Self::RequestHeaders => "get-all-request-header",
160 Self::RequestTrailers => "get-all-request-trailer",
161 Self::ResponseHeaders => "get-all-response-header",
162 Self::ResponseTrailers => "get-all-response-trailer",
163 }
164 }
165
166 const fn get(&self) -> &'static str {
167 match self {
168 Self::RequestHeaders => "get-request-header",
169 Self::RequestTrailers => "get-request-trailer",
170 Self::ResponseHeaders => "get-response-header",
171 Self::ResponseTrailers => "get-response-trailer",
172 }
173 }
174
175 const fn set(&self) -> &'static str {
176 match self {
177 Self::RequestHeaders => "set-request-header",
178 Self::RequestTrailers => "set-request-trailer",
179 Self::ResponseHeaders => "set-response-header",
180 Self::ResponseTrailers => "set-response-trailer",
181 }
182 }
183
184 const fn set_all(&self) -> &'static str {
185 match self {
186 Self::RequestHeaders => "set-all-request-headers",
187 Self::RequestTrailers => "set-all-request-trailers",
188 Self::ResponseHeaders => "set-all-response-headers",
189 Self::ResponseTrailers => "set-all-response-trailers",
190 }
191 }
192
193 const fn add(&self) -> &'static str {
194 match self {
195 Self::RequestHeaders => "add-request-headers",
196 Self::RequestTrailers => "add-request-trailers",
197 Self::ResponseHeaders => "add-response-headers",
198 Self::ResponseTrailers => "add-response-trailers",
199 }
200 }
201
202 const fn remove(&self) -> &'static str {
203 match self {
204 Self::RequestHeaders => "remove-request-headers",
205 Self::RequestTrailers => "remove-request-trailers",
206 Self::ResponseHeaders => "remove-response-headers",
207 Self::ResponseTrailers => "remove-response-trailers",
208 }
209 }
210
211 const fn map(&self) -> MapType {
212 match self {
213 HeaderType::RequestHeaders => MapType::HttpRequestHeaders,
214 HeaderType::RequestTrailers => MapType::HttpRequestTrailers,
215 HeaderType::ResponseHeaders => MapType::HttpResponseHeaders,
216 HeaderType::ResponseTrailers => MapType::HttpResponseTrailers,
217 }
218 }
219}
220
221pub enum HttpType {
223 Request,
224 Response,
225}
226
227impl HttpType {
228 const fn resume(&self) -> &'static str {
229 match self {
230 HttpType::Request => "resume-http-request",
231 HttpType::Response => "resume-http-response",
232 }
233 }
234
235 fn call_resume(&self) -> Result<(), Status> {
236 match self {
237 HttpType::Request => hostcalls::resume_http_request(),
238 HttpType::Response => hostcalls::resume_http_response(),
239 }
240 }
241
242 const fn reset(&self) -> &'static str {
243 match self {
244 HttpType::Request => "reset-http-request",
245 HttpType::Response => "reset-http-response",
246 }
247 }
248
249 fn call_reset(&self) -> Result<(), Status> {
250 match self {
251 HttpType::Request => hostcalls::reset_http_request(),
252 HttpType::Response => hostcalls::reset_http_response(),
253 }
254 }
255
256 const fn get(&self) -> &'static str {
257 match self {
258 HttpType::Request => "get-request-body",
259 HttpType::Response => "get-response-body",
260 }
261 }
262
263 const fn set(&self) -> &'static str {
264 match self {
265 HttpType::Request => "set-request-body",
266 HttpType::Response => "set-response-body",
267 }
268 }
269
270 const fn buffer(&self) -> BufferType {
271 match self {
272 HttpType::Request => BufferType::HttpRequestBody,
273 HttpType::Response => BufferType::HttpResponseBody,
274 }
275 }
276}
277
278#[repr(usize)]
280#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
281#[non_exhaustive]
282pub enum FilterHeadersStatus {
283 Continue = 0,
284 StopIteration = 1,
285 ContinueAndEndStream = 2,
286 StopAllIterationAndBuffer = 3,
287 StopAllIterationAndWatermark = 4,
288}
289
290#[repr(usize)]
292#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
293#[non_exhaustive]
294pub enum FilterTrailersStatus {
295 Continue = 0,
296 StopIteration = 1,
297}
298
299#[repr(usize)]
301#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
302#[non_exhaustive]
303pub enum FilterDataStatus {
304 Continue = 0,
305 StopAllIterationAndBuffer = 1,
306 StopAllIterationAndWatermark = 2,
307 StopIterationNoBuffer = 3,
308}
309
310pub struct RequestHeaders {
312 pub(crate) header_count: usize,
313 pub(crate) end_of_stream: bool,
314 pub(crate) attributes: Attributes,
315}
316
317impl HttpControl for RequestHeaders {
318 const TYPE: HttpType = HttpType::Request;
319
320 fn attributes(&self) -> &Attributes {
321 &self.attributes
322 }
323
324 fn end_of_stream(&self) -> bool {
325 self.end_of_stream
326 }
327}
328
329impl HttpHeaderControl for RequestHeaders {
330 const HEADER_TYPE: HeaderType = HeaderType::RequestHeaders;
331
332 fn header_count(&self) -> usize {
333 self.header_count
334 }
335}
336
337pub struct RequestBody {
338 pub(crate) body_size: usize,
339 pub(crate) end_of_stream: bool,
340 pub(crate) attributes: Attributes,
341}
342
343impl HttpControl for RequestBody {
344 const TYPE: HttpType = HttpType::Request;
345
346 fn attributes(&self) -> &Attributes {
347 &self.attributes
348 }
349
350 fn end_of_stream(&self) -> bool {
351 self.end_of_stream
352 }
353}
354
355impl HttpBodyControl for RequestBody {
356 fn body_size(&self) -> usize {
357 self.body_size
358 }
359}
360
361pub struct RequestTrailers {
362 pub(crate) trailer_count: usize,
363 pub(crate) attributes: Attributes,
364}
365
366impl HttpControl for RequestTrailers {
367 const TYPE: HttpType = HttpType::Request;
368
369 fn attributes(&self) -> &Attributes {
370 &self.attributes
371 }
372}
373
374impl HttpHeaderControl for RequestTrailers {
375 const HEADER_TYPE: HeaderType = HeaderType::RequestTrailers;
376
377 fn header_count(&self) -> usize {
378 self.trailer_count
379 }
380}
381
382pub struct ResponseHeaders {
383 pub(crate) header_count: usize,
384 pub(crate) end_of_stream: bool,
385 pub(crate) attributes: Attributes,
386}
387
388impl HttpControl for ResponseHeaders {
389 const TYPE: HttpType = HttpType::Response;
390
391 fn attributes(&self) -> &Attributes {
392 &self.attributes
393 }
394
395 fn end_of_stream(&self) -> bool {
396 self.end_of_stream
397 }
398}
399
400impl HttpHeaderControl for ResponseHeaders {
401 const HEADER_TYPE: HeaderType = HeaderType::ResponseHeaders;
402
403 fn header_count(&self) -> usize {
404 self.header_count
405 }
406}
407
408pub struct ResponseBody {
409 pub(crate) body_size: usize,
410 pub(crate) end_of_stream: bool,
411 pub(crate) attributes: Attributes,
412}
413
414impl HttpControl for ResponseBody {
415 const TYPE: HttpType = HttpType::Response;
416
417 fn attributes(&self) -> &Attributes {
418 &self.attributes
419 }
420
421 fn end_of_stream(&self) -> bool {
422 self.end_of_stream
423 }
424}
425
426impl HttpBodyControl for ResponseBody {
427 fn body_size(&self) -> usize {
428 self.body_size
429 }
430}
431
432pub struct ResponseTrailers {
433 pub(crate) trailer_count: usize,
434 pub(crate) attributes: Attributes,
435}
436
437impl HttpControl for ResponseTrailers {
438 const TYPE: HttpType = HttpType::Response;
439
440 fn attributes(&self) -> &Attributes {
441 &self.attributes
442 }
443}
444
445impl HttpHeaderControl for ResponseTrailers {
446 const HEADER_TYPE: HeaderType = HeaderType::ResponseTrailers;
447
448 fn header_count(&self) -> usize {
449 self.trailer_count
450 }
451}
452
453#[allow(unused_variables)]
455pub trait HttpContext: BaseContext {
456 fn on_http_request_headers(&mut self, headers: &RequestHeaders) -> FilterHeadersStatus {
458 FilterHeadersStatus::Continue
459 }
460
461 fn on_http_request_body(&mut self, body: &RequestBody) -> FilterDataStatus {
463 FilterDataStatus::Continue
464 }
465
466 fn on_http_request_trailers(&mut self, trailers: &RequestTrailers) -> FilterTrailersStatus {
468 FilterTrailersStatus::Continue
469 }
470
471 fn on_http_response_headers(&mut self, headers: &ResponseHeaders) -> FilterHeadersStatus {
473 FilterHeadersStatus::Continue
474 }
475
476 fn on_http_response_body(&mut self, body: &ResponseBody) -> FilterDataStatus {
478 FilterDataStatus::Continue
479 }
480
481 fn on_http_response_trailers(&mut self, trailers: &ResponseTrailers) -> FilterTrailersStatus {
483 FilterTrailersStatus::Continue
484 }
485}