diff --git a/crates/adapter/src/fastly/core.rs b/crates/adapter/src/fastly/core.rs index e613905e..493d3cc0 100644 --- a/crates/adapter/src/fastly/core.rs +++ b/crates/adapter/src/fastly/core.rs @@ -995,7 +995,9 @@ pub mod fastly_http_req { nwritten: *mut usize, ) -> FastlyStatus { alloc_result!(region_out, region_max_len, nwritten, { - fastly::api::http_req::downstream_compliance_region() + fastly::api::http_req::downstream_compliance_region( + u64::try_from(region_max_len).trapping_unwrap(), + ) }) } diff --git a/lib/src/component/http_req.rs b/lib/src/component/http_req.rs index 902e9fd9..32fb6841 100644 --- a/lib/src/component/http_req.rs +++ b/lib/src/component/http_req.rs @@ -808,8 +808,17 @@ impl http_req::Host for Session { Err(Error::NotAvailable("Client TLS JA4 hash").into()) } - async fn downstream_compliance_region(&mut self) -> Result, types::Error> { - Ok(Vec::from(b"none")) + async fn downstream_compliance_region( + &mut self, + region_max_len: u64, + ) -> Result, types::Error> { + let region = Session::downstream_compliance_region(self); + let region_len = region.len(); + + match u64::try_from(region_len) { + Ok(region_len) if region_len <= region_max_len => Ok(region.into()), + too_large => Err(types::Error::BufferLen(too_large.unwrap_or(0))), + } } async fn original_header_names_get( diff --git a/lib/src/session.rs b/lib/src/session.rs index 754d8f2e..8b1b5615 100644 --- a/lib/src/session.rs +++ b/lib/src/session.rs @@ -38,6 +38,8 @@ use { tokio::sync::oneshot::Sender, }; +const REGION_NONE: &[u8] = b"none"; + /// Data specific to an individual request, including any host-side /// allocations on behalf of the guest processing the request. pub struct Session { @@ -45,6 +47,11 @@ pub struct Session { downstream_client_addr: SocketAddr, /// The IP address and port that received this session. downstream_server_addr: SocketAddr, + /// The compliance region that this request was received in. + /// + /// For now this is just always `"none"`, but we place the field in the session + /// to make it easier to implement custom configuration values later on. + downstream_compliance_region: Vec, /// Handle for the downstream request "parts". NB the backing parts data can be mutated /// or even removed from the relevant map. downstream_req_handle: RequestHandle, @@ -165,6 +172,7 @@ impl Session { Session { downstream_server_addr: server_addr, downstream_client_addr: client_addr, + downstream_compliance_region: Vec::from(REGION_NONE), downstream_req_handle, downstream_req_body_handle, downstream_req_original_headers, @@ -204,6 +212,11 @@ impl Session { self.downstream_server_addr.ip() } + /// Retrieve the compliance region that received the request for this session. + pub fn downstream_compliance_region(&self) -> &[u8] { + self.downstream_compliance_region.as_slice() + } + /// Retrieve the handle corresponding to the downstream request. pub fn downstream_request(&self) -> RequestHandle { self.downstream_req_handle diff --git a/lib/src/wiggle_abi/req_impl.rs b/lib/src/wiggle_abi/req_impl.rs index 954923bc..23cd1ce8 100644 --- a/lib/src/wiggle_abi/req_impl.rs +++ b/lib/src/wiggle_abi/req_impl.rs @@ -308,23 +308,25 @@ impl FastlyHttpReq for Session { region_max_len: u32, nwritten_out: GuestPtr, ) -> Result<(), Error> { - const REGION_NONE: &[u8] = b"none"; - const REGION_NONE_LEN: u32 = 4; + let region = Session::downstream_compliance_region(self); + let region_len = region.len(); - if region_max_len < REGION_NONE_LEN { - // Let the guest know how much we want to write. - memory.write(nwritten_out, REGION_NONE_LEN)?; + match u32::try_from(region_len) { + Ok(region_len) if region_len <= region_max_len => { + memory.copy_from_slice(region, region_out.as_array(region_max_len))?; + memory.write(nwritten_out, region_len.try_into().unwrap_or(0))?; - return Err(Error::BufferLengthError { - buf: "region_out", - len: "region_max_len", - }); - } - - memory.copy_from_slice(REGION_NONE, region_out.as_array(region_max_len))?; - memory.write(nwritten_out, REGION_NONE_LEN)?; + Ok(()) + } + too_large => { + memory.write(nwritten_out, too_large.unwrap_or(0))?; - Ok(()) + Err(Error::BufferLengthError { + buf: "region_out", + len: "region_max_len", + }) + } + } } fn framing_headers_mode_set( diff --git a/lib/wit/deps/fastly/compute.wit b/lib/wit/deps/fastly/compute.wit index d52a8be3..a7dcb7ce 100644 --- a/lib/wit/deps/fastly/compute.wit +++ b/lib/wit/deps/fastly/compute.wit @@ -323,7 +323,7 @@ interface http-req { downstream-tls-ja4: func(max-len: u64) -> result, error>; - downstream-compliance-region: func() -> result, error>; + downstream-compliance-region: func(max-len: u64) -> result, error>; new: func() -> result;