diff --git a/lambda-http/src/response.rs b/lambda-http/src/response.rs index 299a60b2..f2bc9b9a 100644 --- a/lambda-http/src/response.rs +++ b/lambda-http/src/response.rs @@ -23,6 +23,8 @@ use std::borrow::Cow; use std::future::ready; use std::{fmt, future::Future, pin::Pin}; +const X_LAMBDA_HTTP_CONTENT_ENCODING: &str = "x-lambda-http-content-encoding"; + /// Representation of Lambda response #[doc(hidden)] #[derive(Serialize, Debug)] @@ -181,7 +183,7 @@ where return convert_to_binary(self); } - let content_type = if let Some(value) = headers.get(http::header::CONTENT_TYPE) { + let content_type = if let Some(value) = headers.get(CONTENT_TYPE) { value.to_str().unwrap_or_default() } else { // Content-Type and Content-Encoding not set, passthrough as utf8 text @@ -199,6 +201,12 @@ where return convert_to_text(self, content_type); } + if let Some(value) = headers.get(X_LAMBDA_HTTP_CONTENT_ENCODING) { + if value == "text" { + return convert_to_text(self, content_type); + } + } + convert_to_binary(self) } } @@ -242,7 +250,7 @@ pub type BodyFuture = Pin>>; #[cfg(test)] mod tests { - use super::{Body, IntoResponse, LambdaResponse, RequestOrigin}; + use super::{Body, IntoResponse, LambdaResponse, RequestOrigin, X_LAMBDA_HTTP_CONTENT_ENCODING}; use http::{ header::{CONTENT_ENCODING, CONTENT_TYPE}, Response, @@ -250,6 +258,8 @@ mod tests { use hyper::Body as HyperBody; use serde_json::{self, json}; + const SVG_LOGO: &str = include_str!("../tests/data/svg_logo.svg"); + #[tokio::test] async fn json_into_response() { let response = json!({ "hello": "lambda"}).into_response().await; @@ -388,4 +398,52 @@ mod tests { json ) } + + #[tokio::test] + async fn content_type_xml_as_text() { + // Drive the implementation by using `hyper::Body` instead of + // of `aws_lambda_events::encodings::Body` + let response = Response::builder() + .header(CONTENT_TYPE, "image/svg+xml") + .body(HyperBody::from(SVG_LOGO.as_bytes())) + .expect("unable to build http::Response"); + let response = response.into_response().await; + + match response.body() { + Body::Text(body) => assert_eq!(SVG_LOGO, body), + _ => panic!("invalid body"), + } + assert_eq!( + response + .headers() + .get(CONTENT_TYPE) + .map(|h| h.to_str().expect("invalid header")), + Some("image/svg+xml") + ) + } + + #[tokio::test] + async fn content_type_custom_encoding_as_text() { + // Drive the implementation by using `hyper::Body` instead of + // of `aws_lambda_events::encodings::Body` + let response = Response::builder() + // this CONTENT-TYPE is not standard, and would yield a binary response + .header(CONTENT_TYPE, "image/svg") + .header(X_LAMBDA_HTTP_CONTENT_ENCODING, "text") + .body(HyperBody::from(SVG_LOGO.as_bytes())) + .expect("unable to build http::Response"); + let response = response.into_response().await; + + match response.body() { + Body::Text(body) => assert_eq!(SVG_LOGO, body), + _ => panic!("invalid body"), + } + assert_eq!( + response + .headers() + .get(CONTENT_TYPE) + .map(|h| h.to_str().expect("invalid header")), + Some("image/svg") + ) + } } diff --git a/lambda-http/tests/data/svg_logo.svg b/lambda-http/tests/data/svg_logo.svg new file mode 100644 index 00000000..3dd03b6c --- /dev/null +++ b/lambda-http/tests/data/svg_logo.svg @@ -0,0 +1,49 @@ + + + SVG logo combined with the W3C logo, set horizontally + The logo combines three entities displayed horizontally: the W3C logo with the text 'W3C'; the drawing of a flower or star shape with eight arms; and the text 'SVG'. These three entities are set horizontally. + + + + + SVG logo combined with the W3C logo + image/svg+xml + + 2007-11-01 + + + + The logo combines three entities displayed horizontally: the W3C logo with the text 'W3C'; the drawing of a flower or star shape with eight arms; and the text 'SVG'. These three entities are set horizontally. + + + + + + W3C + SVG + + + + + + + + + + + + + + + + \ No newline at end of file