From 9725fe2c28f2526fee12b6a0638c227fb4faf4ae Mon Sep 17 00:00:00 2001 From: Harold Sun Date: Fri, 20 Mar 2026 06:08:17 +0000 Subject: [PATCH] fix: preserve response body when error_status_codes triggers Previously, when AWS_LWA_ERROR_STATUS_CODES matched a response status code, the adapter discarded the HTTP response body and returned a generic error message. This broke Step Functions workflows that rely on error payloads for branching and retry logic. Now the error includes a JSON object with both the status code and the original response body: {"statusCode":502,"body":"Bad Gateway"} This allows consumers like Step Functions to inspect the original error details for decision making. Fixes #609 --- Cargo.toml | 2 +- src/lib.rs | 13 +++++++++++-- tests/integ_tests/main.rs | 4 +++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 650c13a3..cb711f05 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ exclude = ["examples"] bytes = "1.9.0" http = "1.2.0" http-body = "1.0.1" +http-body-util = "0.1.0" hyper = { version = "1.5.2", features = ["client"] } hyper-util = "0.1.10" lambda_http = { version = "1.1.1", default-features = false, features = [ @@ -51,7 +52,6 @@ url = "2.5.4" [dev-dependencies] flate2 = "1.0.25" httpmock = "0.8.2" -http-body-util = "0.1.0" http-body = "1.0" hyper-rustls = "0.27" aws-sigv4 = "1.2.3" diff --git a/src/lib.rs b/src/lib.rs index 522f9bd9..60677209 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -97,6 +97,7 @@ use http::{ Method, StatusCode, }; use http_body::Body as HttpBody; +use http_body_util::BodyExt; use hyper::body::Incoming; use hyper_util::client::legacy::connect::HttpConnector; use hyper_util::client::legacy::Client; @@ -952,9 +953,17 @@ impl Adapter { if let Some(error_codes) = &self.error_status_codes { let status = app_response.status().as_u16(); if error_codes.contains(&status) { + let body_bytes = app_response + .into_body() + .collect() + .await + .map(|c| c.to_bytes()) + .unwrap_or_default(); + let body_str = String::from_utf8_lossy(&body_bytes); return Err(Error::from(format!( - "Request failed with configured error status code: {}", - status + "{{\"statusCode\":{},\"body\":{}}}", + status, + serde_json::to_string(&*body_str).unwrap_or_else(|_| format!("\"{}\"", body_str)) ))); } } diff --git a/tests/integ_tests/main.rs b/tests/integ_tests/main.rs index 5961e82c..0238618e 100644 --- a/tests/integ_tests/main.rs +++ b/tests/integ_tests/main.rs @@ -740,7 +740,9 @@ async fn test_http_error_status_codes() { let result = adapter.call(request).await; assert!(result.is_err(), "Expected error response for status code 502"); - assert!(result.unwrap_err().to_string().contains("502")); + let err_msg = result.unwrap_err().to_string(); + assert!(err_msg.contains("502"), "Error should contain status code"); + assert!(err_msg.contains("Bad Gateway"), "Error should preserve response body"); // Assert endpoint was called error_endpoint.assert();