Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions crates/http-service/src/executor/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ mod tests {
let http_service: HttpService<TestContext, TestStats> =
assert_ok!(ServiceBuilder::new(context).build());

let res = assert_ok!(http_service.handle_request("1".to_smolstr(), req).await);
let res = assert_ok!(http_service.handle_request(req).await);
assert_eq!(StatusCode::OK, res.status());
let headers = res.headers();
assert_eq!(4, headers.len());
Expand Down Expand Up @@ -481,7 +481,7 @@ mod tests {
let http_service: HttpService<TestContext, TestStats> =
assert_ok!(ServiceBuilder::new(context).build());

let res = assert_ok!(http_service.handle_request("2".to_smolstr(), req).await);
let res = assert_ok!(http_service.handle_request(req).await);
assert_eq!(FASTEDGE_EXECUTION_TIMEOUT, res.status());
let headers = res.headers();
assert_eq!(4, headers.len());
Expand Down Expand Up @@ -545,7 +545,7 @@ mod tests {
let http_service: HttpService<TestContext, TestStats> =
assert_ok!(ServiceBuilder::new(context).build());

let res = assert_ok!(http_service.handle_request("3".to_smolstr(), req).await);
let res = assert_ok!(http_service.handle_request(req).await);
assert_eq!(FASTEDGE_OUT_OF_MEMORY, res.status());
let headers = res.headers();
assert_eq!(4, headers.len());
Expand Down Expand Up @@ -586,7 +586,7 @@ mod tests {

let http_service: HttpService<TestContext, TestStats> =
assert_ok!(ServiceBuilder::new(context).build());
let res = assert_ok!(http_service.handle_request("4".to_smolstr(), req).await);
let res = assert_ok!(http_service.handle_request(req).await);
assert_eq!(StatusCode::NOT_FOUND, res.status());
assert_eq!(0, res.headers().len());
}
Expand Down Expand Up @@ -614,7 +614,7 @@ mod tests {

let http_service: HttpService<TestContext, TestStats> =
assert_ok!(ServiceBuilder::new(context).build());
let res = assert_ok!(http_service.handle_request("5".to_smolstr(), req).await);
let res = assert_ok!(http_service.handle_request(req).await);
assert_eq!(StatusCode::NOT_FOUND, res.status());
assert_eq!(0, res.headers().len());
}
Expand Down Expand Up @@ -642,7 +642,7 @@ mod tests {

let http_service: HttpService<TestContext, TestStats> =
assert_ok!(ServiceBuilder::new(context).build());
let res = assert_ok!(http_service.handle_request("6".to_smolstr(), req).await);
let res = assert_ok!(http_service.handle_request(req).await);
assert_eq!(StatusCode::TOO_MANY_REQUESTS, res.status());
assert_eq!(0, res.headers().len());
}
Expand Down Expand Up @@ -670,7 +670,7 @@ mod tests {

let http_service: HttpService<TestContext, TestStats> =
assert_ok!(ServiceBuilder::new(context).build());
let res = assert_ok!(http_service.handle_request("7".to_smolstr(), req).await);
let res = assert_ok!(http_service.handle_request(req).await);
assert_eq!(StatusCode::NOT_ACCEPTABLE, res.status());
assert_eq!(0, res.headers().len());
}
Expand Down Expand Up @@ -703,7 +703,7 @@ mod tests {
let http_service: HttpService<TestContext, TestStats> =
assert_ok!(ServiceBuilder::new(context).build());

let res = assert_ok!(http_service.handle_request("8".to_smolstr(), req).await);
let res = assert_ok!(http_service.handle_request(req).await);
assert_eq!(StatusCode::OK, res.status());
let headers = res.headers();
assert_eq!(4, headers.len());
Expand Down Expand Up @@ -742,7 +742,7 @@ mod tests {
let http_service: HttpService<TestContext, TestStats> =
assert_ok!(ServiceBuilder::new(context).build());

let res = assert_ok!(http_service.handle_request("9".to_smolstr(), req).await);
let res = assert_ok!(http_service.handle_request(req).await);
// Reaching OK proves we resolved via lookup_by_id (otherwise our mock for
// lookup_by_name path would have produced the same status, but we also
// verify in `test_fastedge_app_id_invalid_returns_not_found` below that
Expand Down Expand Up @@ -776,7 +776,7 @@ mod tests {
let http_service: HttpService<TestContext, TestStats> =
assert_ok!(ServiceBuilder::new(context).build());

let res = assert_ok!(http_service.handle_request("10".to_smolstr(), req).await);
let res = assert_ok!(http_service.handle_request(req).await);
assert_eq!(StatusCode::NOT_FOUND, res.status());
assert_eq!(0, res.headers().len());
}
Expand Down Expand Up @@ -807,7 +807,7 @@ mod tests {
let http_service: HttpService<TestContext, TestStats> =
assert_ok!(ServiceBuilder::new(context).build());

let res = assert_ok!(http_service.handle_request("11".to_smolstr(), req).await);
let res = assert_ok!(http_service.handle_request(req).await);
assert_eq!(StatusCode::NOT_FOUND, res.status());
assert_eq!(0, res.headers().len());
}
Expand Down Expand Up @@ -837,7 +837,7 @@ mod tests {
let http_service: HttpService<TestContext, TestStats> =
assert_ok!(ServiceBuilder::new(context).build());

let res = assert_ok!(http_service.handle_request("12".to_smolstr(), req).await);
let res = assert_ok!(http_service.handle_request(req).await);
assert_eq!(StatusCode::NOT_FOUND, res.status());
assert_eq!(0, res.headers().len());
}
Expand Down Expand Up @@ -869,7 +869,7 @@ mod tests {
let http_service: HttpService<TestContext, TestStats> =
assert_ok!(ServiceBuilder::new(context).build());

let res = assert_ok!(http_service.handle_request("13".to_smolstr(), req).await);
let res = assert_ok!(http_service.handle_request(req).await);
assert_eq!(StatusCode::NOT_FOUND, res.status());
assert_eq!(0, res.headers().len());
}
Expand All @@ -895,7 +895,7 @@ mod tests {
let http_service: HttpService<TestContext, TestStats> =
assert_ok!(ServiceBuilder::new(context).build());

let res = assert_ok!(http_service.handle_request("14".to_smolstr(), req).await);
let res = assert_ok!(http_service.handle_request(req).await);
assert_eq!(StatusCode::NOT_FOUND, res.status());
assert_eq!(0, res.headers().len());
}
Expand Down
58 changes: 37 additions & 21 deletions crates/http-service/src/executor/wasi_http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ use crate::state::HttpState;
use ::http::{HeaderMap, Request, Response, Uri, header};
use anyhow::{Context, anyhow, bail};
use async_trait::async_trait;
use http_backend::Backend;
use http_backend::{Backend, SERVER_NAME_HEADER};
use http_body_util::{BodyExt, Full};
use hyper::body::Body;
use runtime::util::stats::{StatsTimer, StatsVisitor};
use runtime::{InstancePre, store::StoreBuilder};
use smol_str::SmolStr;
use tracing::Instrument;
use wasmtime_wasi_http::bindings::ProxyPre;
use wasmtime_wasi_http::bindings::http::types::Scheme;
use wasmtime_wasi_http::{WasiHttpView, body::HyperOutgoingBody};
Expand Down Expand Up @@ -46,7 +47,19 @@ where
let (mut parts, body) = req.into_parts();

const LOCALHOST: SmolStr = SmolStr::new_inline("localhost");
let backend_hostname = self.backend.hostname().unwrap_or(LOCALHOST);

// Resolve backend hostname using the following precedence:
Comment thread
ruslanti marked this conversation as resolved.
// 1. `server_name` request header (if set and valid UTF-8)
// 2. backend's configured hostname
// 3. fallback to "localhost"
let backend_hostname: SmolStr = parts
.headers
.get(SERVER_NAME_HEADER)
.and_then(|v| v.to_str().ok())
.map(SmolStr::from)
.or_else(|| self.backend.hostname())
.unwrap_or(LOCALHOST);

let hostname = match backend_hostname.find('.') {
None => backend_hostname.as_str(),
Some(i) => {
Expand Down Expand Up @@ -123,25 +136,28 @@ where
let proxy = proxy_pre.instantiate_async(&mut store).await?;

let task_stats = stats.clone();
let task = tokio::task::spawn(async move {
let duration = Duration::from_millis(store.data().timeout);
if let Err(e) = tokio::time::timeout(
duration,
proxy
.wasi_http_incoming_handler()
.call_handle(&mut store, req, out),
)
.await?
{
tracing::warn!(cause=?e, "incoming handler");
return Err(e);
};

drop(stats_timer); // Stop timing for stats
task_stats.memory_used(store.memory_used() as u64);

Ok(())
});
let task = tokio::task::spawn(
async move {
let duration = Duration::from_millis(store.data().timeout);
if let Err(e) = tokio::time::timeout(
duration,
proxy
.wasi_http_incoming_handler()
.call_handle(&mut store, req, out),
)
.await?
{
tracing::warn!(cause=?e, "incoming handler");
return Err(e);
};

drop(stats_timer); // Stop timing for stats
task_stats.memory_used(store.memory_used() as u64);

Ok(())
}
.in_current_span(),
);

match receiver.await {
Ok(Ok(response)) => {
Expand Down
17 changes: 7 additions & 10 deletions crates/http-service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,16 +150,13 @@ where
Ok((stream, _)) => {
tracing::debug!(remote=?stream.peer_addr(), "new http connection");
let connection = self_.clone();
use tracing::Instrument;
let io = TokioIo::new(stream);

let service = service_fn(move |req| {
let self_ = connection.clone();
let request_id = remote_traceparent(&req);
async move {
self_
.handle_request(request_id.clone(), req)
.instrument(tracing::debug_span!("http", ?request_id))
.handle_request(req)
.await
}
});
Expand Down Expand Up @@ -269,13 +266,13 @@ where
/// handle HTTP request.
async fn handle_request<B>(
&self,
request_id: SmolStr,
mut request: hyper::Request<B>,
) -> Result<hyper::Response<HyperOutgoingBody>>
where
B: BodyExt + Send,
<B as Body>::Data: Send,
{
let traceparent = remote_traceparent(&request);
request
.headers_mut()
.extend(app_req_headers(self.context.append_headers()));
Expand All @@ -285,13 +282,13 @@ where
Err(error) => {
#[cfg(feature = "metrics")]
metrics::metrics(AppResult::UNKNOWN, HTTP_LABEL, None, None);
tracing::info!(cause=?error, "App name not provided");
tracing::info!(cause=?error, traceparent = %traceparent, "App name not provided");
return not_found();
}
Ok(app_name) => app_name,
};

let span = tracing::info_span!("handle", app = %app_name);
let span = tracing::info_span!("http", app = %app_name, traceparent = %traceparent);
let _enter = span.enter();

Comment thread
ruslanti marked this conversation as resolved.
// lookup for application config and binary_id
Expand Down Expand Up @@ -359,7 +356,7 @@ where
}
};

let stats = self.context.new_stats_row(&request_id, &app_name, &cfg);
let stats = self.context.new_stats_row(&traceparent, &app_name, &cfg);

let response = match executor
.execute(request, stats.clone())
Expand All @@ -383,7 +380,7 @@ where
let (status_code, fail_reason, msg, internal_code) = map_err(error);
stats.status_code(status_code);
stats.fail_reason(fail_reason as i32);
tracing::debug!(?fail_reason, ?request_id, "stats");
tracing::debug!(?fail_reason, ?traceparent, "stats");

#[cfg(feature = "metrics")]
metrics::metrics(
Expand Down Expand Up @@ -487,7 +484,7 @@ fn map_err(error: Error) -> (u16, AppResult, HyperOutgoingBody, u16) {
(status_code, fail_reason, msg, internal_code)
}

fn remote_traceparent(req: &hyper::Request<hyper::body::Incoming>) -> SmolStr {
fn remote_traceparent<B>(req: &hyper::Request<B>) -> SmolStr {
req.headers()
.get(TRACEPARENT)
.and_then(|v| v.to_str().ok())
Expand Down
Loading