spin_trigger_http/
outbound_http.rs1use std::{
2 net::{IpAddr, Ipv4Addr, SocketAddr},
3 sync::Arc,
4};
5
6use http::uri::Scheme;
7use spin_core::async_trait;
8use spin_factor_outbound_http::intercept::{self, InterceptOutcome, InterceptRequest};
9use spin_factor_outbound_networking::config::allowed_hosts::parse_service_chaining_target;
10use spin_factors::RuntimeFactors;
11use spin_http::routes::RouteMatch;
12use wasmtime::ToWasmtimeResult;
13use wasmtime_wasi_http::p2::{HttpError, HttpResult};
14
15use crate::HttpServer;
16
17pub struct OutboundHttpInterceptor<F: RuntimeFactors> {
19 server: Arc<HttpServer<F>>,
20}
21
22impl<F: RuntimeFactors> OutboundHttpInterceptor<F> {
23 pub fn new(server: Arc<HttpServer<F>>) -> Self {
24 Self { server }
25 }
26}
27
28const CHAINED_CLIENT_ADDR: SocketAddr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0);
29
30#[async_trait]
31impl<F: RuntimeFactors> intercept::OutboundHttpInterceptor for OutboundHttpInterceptor<F> {
32 async fn intercept(&self, request: InterceptRequest) -> HttpResult<InterceptOutcome> {
33 if let Some(component_id) = parse_service_chaining_target(request.uri()) {
35 let req = request.into_hyper_request();
36 let path = req.uri().path().to_owned();
37 let route_match = RouteMatch::synthetic(component_id, path);
38 let resp = self
39 .server
40 .handle_trigger_route(req, route_match, Scheme::HTTP, CHAINED_CLIENT_ADDR)
41 .await
42 .to_wasmtime_result()
43 .map_err(HttpError::trap)?;
44 Ok(InterceptOutcome::Complete(resp))
45 } else {
46 Ok(InterceptOutcome::Continue(request))
47 }
48 }
49}