Skip to content

Commit a8aed1a

Browse files
duncanistaastuyveRomainMuller
authored
fix(proxy): ensure correct headers are set when forwarding request (#768)
# What? Fixes an issue where proxy would fail because a response could come as a streamed buffer # Why? We were not taking into account that we are collecting the body before even forwarding the request to the Lambda Runtime, so headers will sent `as-is`. Causing issues when a streamed buffer arrived to ourselves as `transfer-encoding: chunked` which will confuse the runtime since we are proxying it already. # Notes Also added a `env` var check where you can enable proxy as Go, through the `DD_EXPERIMENTAL_PROXY_ENABLED=true` --------- Co-authored-by: AJ Stuyvenberg <aj.stuyvenberg@datadoghq.com> Co-authored-by: Romain Marcadier <romain.marcadier@datadoghq.com>
1 parent 5fbe50d commit a8aed1a

2 files changed

Lines changed: 21 additions & 4 deletions

File tree

bottlecap/src/proxy/interceptor.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,12 @@ fn build_forward_response(
304304

305305
if let Some(h) = forward_response.headers_mut() {
306306
*h = parts.headers;
307+
308+
// Since the body has been already collected, we can set the content-length header instead.
309+
if h.contains_key("transfer-encoding") {
310+
h.remove("transfer-encoding");
311+
h.insert("content-length", body_bytes.len().to_string().parse()?);
312+
}
307313
}
308314

309315
let forward_response = forward_response.body(Body::from(body_bytes))?;
@@ -333,6 +339,12 @@ fn build_proxy_request(
333339

334340
if let Some(h) = request.headers_mut() {
335341
*h = parts.headers.clone();
342+
343+
// Since the body has been already collected, we can set the content-length header instead.
344+
if h.contains_key("transfer-encoding") {
345+
h.remove("transfer-encoding");
346+
h.insert("content-length", body_bytes.len().to_string().parse()?);
347+
}
336348
}
337349

338350
let request = request.body(Body::from(body_bytes))?;

bottlecap/src/proxy/mod.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::sync::Arc;
1+
use std::{env, sync::Arc};
22

33
use crate::config::{Config, aws::AwsConfig};
44

@@ -18,14 +18,19 @@ pub fn should_start_proxy(config: &Arc<Config>, aws_config: Arc<AwsConfig>) -> b
1818
.as_ref()
1919
.is_some_and(|s| s.eq("/opt/datadog_wrapper"));
2020

21-
lwa_proxy_set || (datadog_wrapper_set && config.serverless_appsec_enabled)
21+
// We are not setting this as a config option because we will only allow it as an experimental feature.
22+
// It is mainly expected to be used in a development environment.
23+
let experimental_proxy_enabled =
24+
env::var("DD_EXPERIMENTAL_ENABLE_PROXY").is_ok_and(|v| v.to_lowercase().eq("true"));
25+
26+
lwa_proxy_set
27+
|| (datadog_wrapper_set && (config.serverless_appsec_enabled || experimental_proxy_enabled))
2228
}
2329

2430
#[cfg(test)]
2531
mod tests {
26-
use std::time::Instant;
27-
2832
use super::*;
33+
use std::time::Instant;
2934

3035
#[test]
3136
fn test_should_start_proxy_everything_set() {

0 commit comments

Comments
 (0)