spin_factor_outbound_http/
intercept.rs1use http::{Request, Response};
2use http_body_util::{BodyExt, Full};
3use spin_world::async_trait;
4use wasmtime_wasi_http::{body::HyperOutgoingBody, HttpResult};
5
6pub type HyperBody = HyperOutgoingBody;
7
8#[async_trait]
11pub trait OutboundHttpInterceptor: Send + Sync {
12 async fn intercept(&self, request: InterceptRequest) -> HttpResult<InterceptOutcome>;
22}
23
24pub enum InterceptOutcome {
26 Continue(InterceptRequest),
29 Complete(Response<HyperBody>),
32}
33
34pub struct InterceptRequest {
40 inner: Request<()>,
41 body: InterceptBody,
42}
43
44enum InterceptBody {
45 Hyper(HyperBody),
46 Vec(Vec<u8>),
47}
48
49impl InterceptRequest {
50 pub fn into_hyper_request(self) -> Request<HyperBody> {
51 let (parts, ()) = self.inner.into_parts();
52 Request::from_parts(parts, self.body.into())
53 }
54
55 pub(crate) fn into_vec_request(self) -> Option<Request<Vec<u8>>> {
56 let InterceptBody::Vec(bytes) = self.body else {
57 return None;
58 };
59 let (parts, ()) = self.inner.into_parts();
60 Some(Request::from_parts(parts, bytes))
61 }
62}
63
64impl std::ops::Deref for InterceptRequest {
65 type Target = Request<()>;
66
67 fn deref(&self) -> &Self::Target {
68 &self.inner
69 }
70}
71
72impl std::ops::DerefMut for InterceptRequest {
73 fn deref_mut(&mut self) -> &mut Self::Target {
74 &mut self.inner
75 }
76}
77
78impl From<Request<HyperBody>> for InterceptRequest {
79 fn from(req: Request<HyperBody>) -> Self {
80 let (parts, body) = req.into_parts();
81 Self {
82 inner: Request::from_parts(parts, ()),
83 body: InterceptBody::Hyper(body),
84 }
85 }
86}
87
88impl From<Request<Vec<u8>>> for InterceptRequest {
89 fn from(req: Request<Vec<u8>>) -> Self {
90 let (parts, body) = req.into_parts();
91 Self {
92 inner: Request::from_parts(parts, ()),
93 body: InterceptBody::Vec(body),
94 }
95 }
96}
97
98impl From<InterceptBody> for HyperBody {
99 fn from(body: InterceptBody) -> Self {
100 match body {
101 InterceptBody::Hyper(body) => body,
102 InterceptBody::Vec(bytes) => {
103 Full::new(bytes.into()).map_err(|err| match err {}).boxed()
104 }
105 }
106 }
107}