-
Notifications
You must be signed in to change notification settings - Fork 265
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Factors] Change how incoming-request.authority
is set.
#2723
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ use std::{ | |
sync::Arc, | ||
}; | ||
|
||
use http::uri::Scheme; | ||
use spin_factor_outbound_http::{ | ||
HostFutureIncomingResponse, InterceptOutcome, OutgoingRequestConfig, Request, SelfRequestOrigin, | ||
}; | ||
|
@@ -42,7 +43,7 @@ impl spin_factor_outbound_http::OutboundHttpInterceptor for OutboundHttpIntercep | |
let server = self.server.clone(); | ||
let resp_fut = async move { | ||
match server | ||
.handle_trigger_route(req, route_match, CHAINED_CLIENT_ADDR) | ||
.handle_trigger_route(req, route_match, Scheme::HTTP, CHAINED_CLIENT_ADDR) | ||
.await | ||
{ | ||
Ok(resp) => Ok(Ok(IncomingResponse { | ||
Comment on lines
43
to
49
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if we should be setting the |
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,7 @@ use crate::{ | |
}; | ||
|
||
pub struct HttpServer { | ||
/// The address the server is listening on. | ||
listen_addr: SocketAddr, | ||
trigger_app: TriggerApp, | ||
router: Router, | ||
|
@@ -74,7 +75,8 @@ impl HttpServer { | |
self.print_startup_msgs("http", &listener)?; | ||
loop { | ||
let (stream, client_addr) = listener.accept().await?; | ||
self.clone().serve_connection(stream, client_addr); | ||
self.clone() | ||
.serve_connection(stream, Scheme::HTTP, client_addr); | ||
} | ||
} | ||
|
||
|
@@ -88,28 +90,32 @@ impl HttpServer { | |
loop { | ||
let (stream, client_addr) = listener.accept().await?; | ||
match acceptor.accept(stream).await { | ||
Ok(stream) => self.clone().serve_connection(stream, client_addr), | ||
Ok(stream) => self | ||
.clone() | ||
.serve_connection(stream, Scheme::HTTPS, client_addr), | ||
Err(err) => tracing::error!(?err, "Failed to start TLS session"), | ||
} | ||
} | ||
} | ||
|
||
/// Handles incoming requests using an HTTP executor. | ||
/// | ||
/// This method handles well known paths and routes requests to the handler when the router | ||
/// matches the requests path. | ||
async fn handle( | ||
self: &Arc<Self>, | ||
mut req: Request<Body>, | ||
scheme: Scheme, | ||
server_scheme: Scheme, | ||
client_addr: SocketAddr, | ||
) -> anyhow::Result<Response<Body>> { | ||
set_req_uri(&mut req, scheme, self.listen_addr)?; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could this be done at the top of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Putting it in The call graph is: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah gotcha. Perhaps it would make sense to split the scheme and host updates? 🤔 |
||
strip_forbidden_headers(&mut req); | ||
|
||
spin_telemetry::extract_trace_context(&req); | ||
|
||
tracing::info!("Processing request on URI {}", req.uri()); | ||
|
||
let path = req.uri().path().to_string(); | ||
|
||
tracing::info!("Processing request on path '{path}'"); | ||
|
||
// Handle well-known spin paths | ||
if let Some(well_known) = path.strip_prefix(spin_http::WELL_KNOWN_PREFIX) { | ||
return match well_known { | ||
|
@@ -124,19 +130,22 @@ impl HttpServer { | |
|
||
match self.router.route(&path) { | ||
Ok(route_match) => { | ||
self.handle_trigger_route(req, route_match, client_addr) | ||
self.handle_trigger_route(req, route_match, server_scheme, client_addr) | ||
.await | ||
} | ||
Err(_) => Self::not_found(NotFoundRouteKind::Normal(path.to_string())), | ||
} | ||
} | ||
|
||
/// Handles a successful route match. | ||
pub async fn handle_trigger_route( | ||
self: &Arc<Self>, | ||
req: Request<Body>, | ||
mut req: Request<Body>, | ||
route_match: RouteMatch, | ||
server_scheme: Scheme, | ||
client_addr: SocketAddr, | ||
) -> anyhow::Result<Response<Body>> { | ||
set_req_uri(&mut req, server_scheme.clone())?; | ||
let app_id = self | ||
.trigger_app | ||
.app() | ||
|
@@ -155,9 +164,15 @@ impl HttpServer { | |
let mut instance_builder = self.trigger_app.prepare(component_id)?; | ||
|
||
// Set up outbound HTTP request origin and service chaining | ||
let uri = req.uri(); | ||
let origin = SelfRequestOrigin::from_uri(uri) | ||
.with_context(|| format!("invalid request URI {uri:?}"))?; | ||
let origin = SelfRequestOrigin { | ||
scheme: server_scheme, | ||
authority: self.listen_addr.to_string().parse().with_context(|| { | ||
format!( | ||
"server address '{}' is not a valid authority", | ||
self.listen_addr | ||
) | ||
})?, | ||
}; | ||
rylev marked this conversation as resolved.
Show resolved
Hide resolved
|
||
instance_builder | ||
.factor_builders() | ||
.outbound_http() | ||
|
@@ -259,6 +274,7 @@ impl HttpServer { | |
fn serve_connection<S: AsyncRead + AsyncWrite + Unpin + Send + 'static>( | ||
self: Arc<Self>, | ||
stream: S, | ||
server_scheme: Scheme, | ||
client_addr: SocketAddr, | ||
) { | ||
task::spawn(async move { | ||
|
@@ -267,7 +283,11 @@ impl HttpServer { | |
.serve_connection( | ||
TokioIo::new(stream), | ||
service_fn(move |request| { | ||
self.clone().instrumented_service_fn(client_addr, request) | ||
self.clone().instrumented_service_fn( | ||
server_scheme.clone(), | ||
client_addr, | ||
request, | ||
) | ||
}), | ||
) | ||
.await | ||
|
@@ -279,6 +299,7 @@ impl HttpServer { | |
|
||
async fn instrumented_service_fn( | ||
self: Arc<Self>, | ||
server_scheme: Scheme, | ||
client_addr: SocketAddr, | ||
request: Request<Incoming>, | ||
) -> anyhow::Result<Response<HyperOutgoingBody>> { | ||
|
@@ -291,7 +312,7 @@ impl HttpServer { | |
body.map_err(wasmtime_wasi_http::hyper_response_error) | ||
.boxed() | ||
}), | ||
Scheme::HTTP, | ||
server_scheme, | ||
client_addr, | ||
) | ||
.await; | ||
|
@@ -322,11 +343,21 @@ impl HttpServer { | |
|
||
/// The incoming request's scheme and authority | ||
/// | ||
/// The incoming request's URI is relative to the server, so we need to set the scheme and authority | ||
fn set_req_uri(req: &mut Request<Body>, scheme: Scheme, addr: SocketAddr) -> anyhow::Result<()> { | ||
/// The incoming request's URI is relative to the server, so we need to set the scheme and authority. | ||
/// The `Host` header is used to set the authority. This function will error if no `Host` header is | ||
/// present or if it is not parsable as an `Authority`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Based on hyperium/hyper#1612 I believe this should also consider the |
||
fn set_req_uri(req: &mut Request<Body>, scheme: Scheme) -> anyhow::Result<()> { | ||
let uri = req.uri().clone(); | ||
let mut parts = uri.into_parts(); | ||
let authority = format!("{}:{}", addr.ip(), addr.port()).parse().unwrap(); | ||
let headers = req.headers(); | ||
let host_header = headers | ||
.get(http::header::HOST) | ||
.context("missing 'Host' header")? | ||
.to_str() | ||
.context("'Host' header is not valid UTF-8")?; | ||
let authority = host_header | ||
.parse() | ||
.context("'Host' header contains an invalid authority")?; | ||
parts.scheme = Some(scheme); | ||
parts.authority = Some(authority); | ||
*req.uri_mut() = Uri::from_parts(parts).unwrap(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't change this; the CLI flag is
--listen
...There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hear ya. I wanted to draw attention to the fact that this might not be the actual
SocketAddr
the socket is listening on (in the case of a 0 port), but perhaps that's not worth the potential confusion in the other direction.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the way, the CLI arg is actually
--address
... But I'll still change it back.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately it is a trick: