spin_factor_outbound_http/
intercept.rsuse http::{Request, Response};
use http_body_util::{BodyExt, Full};
use spin_world::async_trait;
use wasmtime_wasi_http::{body::HyperOutgoingBody, HttpResult};
pub type HyperBody = HyperOutgoingBody;
#[async_trait]
pub trait OutboundHttpInterceptor: Send + Sync {
async fn intercept(&self, request: InterceptRequest) -> HttpResult<InterceptOutcome>;
}
pub enum InterceptOutcome {
Continue(InterceptRequest),
Complete(Response<HyperBody>),
}
pub struct InterceptRequest {
inner: Request<()>,
body: InterceptBody,
}
enum InterceptBody {
Hyper(HyperBody),
Vec(Vec<u8>),
}
impl InterceptRequest {
pub fn into_hyper_request(self) -> Request<HyperBody> {
let (parts, ()) = self.inner.into_parts();
Request::from_parts(parts, self.body.into())
}
pub(crate) fn into_vec_request(self) -> Option<Request<Vec<u8>>> {
let InterceptBody::Vec(bytes) = self.body else {
return None;
};
let (parts, ()) = self.inner.into_parts();
Some(Request::from_parts(parts, bytes))
}
}
impl std::ops::Deref for InterceptRequest {
type Target = Request<()>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl std::ops::DerefMut for InterceptRequest {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl From<Request<HyperBody>> for InterceptRequest {
fn from(req: Request<HyperBody>) -> Self {
let (parts, body) = req.into_parts();
Self {
inner: Request::from_parts(parts, ()),
body: InterceptBody::Hyper(body),
}
}
}
impl From<Request<Vec<u8>>> for InterceptRequest {
fn from(req: Request<Vec<u8>>) -> Self {
let (parts, body) = req.into_parts();
Self {
inner: Request::from_parts(parts, ()),
body: InterceptBody::Vec(body),
}
}
}
impl From<InterceptBody> for HyperBody {
fn from(body: InterceptBody) -> Self {
match body {
InterceptBody::Hyper(body) => body,
InterceptBody::Vec(bytes) => {
Full::new(bytes.into()).map_err(|err| match err {}).boxed()
}
}
}
}