Skip to content

Commit 6fd5270

Browse files
authored
Add custom response header to force text encoding (#533)
This allows users to force text encoding on responses that the runtime doesn't consider text and would return binary data otherwise. Signed-off-by: David Calavera <[email protected]> Signed-off-by: David Calavera <[email protected]>
1 parent bd8896a commit 6fd5270

File tree

2 files changed

+109
-2
lines changed

2 files changed

+109
-2
lines changed

lambda-http/src/response.rs

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ use std::borrow::Cow;
2323
use std::future::ready;
2424
use std::{fmt, future::Future, pin::Pin};
2525

26+
const X_LAMBDA_HTTP_CONTENT_ENCODING: &str = "x-lambda-http-content-encoding";
27+
2628
/// Representation of Lambda response
2729
#[doc(hidden)]
2830
#[derive(Serialize, Debug)]
@@ -181,7 +183,7 @@ where
181183
return convert_to_binary(self);
182184
}
183185

184-
let content_type = if let Some(value) = headers.get(http::header::CONTENT_TYPE) {
186+
let content_type = if let Some(value) = headers.get(CONTENT_TYPE) {
185187
value.to_str().unwrap_or_default()
186188
} else {
187189
// Content-Type and Content-Encoding not set, passthrough as utf8 text
@@ -199,6 +201,12 @@ where
199201
return convert_to_text(self, content_type);
200202
}
201203

204+
if let Some(value) = headers.get(X_LAMBDA_HTTP_CONTENT_ENCODING) {
205+
if value == "text" {
206+
return convert_to_text(self, content_type);
207+
}
208+
}
209+
202210
convert_to_binary(self)
203211
}
204212
}
@@ -242,14 +250,16 @@ pub type BodyFuture = Pin<Box<dyn Future<Output = Body>>>;
242250

243251
#[cfg(test)]
244252
mod tests {
245-
use super::{Body, IntoResponse, LambdaResponse, RequestOrigin};
253+
use super::{Body, IntoResponse, LambdaResponse, RequestOrigin, X_LAMBDA_HTTP_CONTENT_ENCODING};
246254
use http::{
247255
header::{CONTENT_ENCODING, CONTENT_TYPE},
248256
Response,
249257
};
250258
use hyper::Body as HyperBody;
251259
use serde_json::{self, json};
252260

261+
const SVG_LOGO: &str = include_str!("../tests/data/svg_logo.svg");
262+
253263
#[tokio::test]
254264
async fn json_into_response() {
255265
let response = json!({ "hello": "lambda"}).into_response().await;
@@ -388,4 +398,52 @@ mod tests {
388398
json
389399
)
390400
}
401+
402+
#[tokio::test]
403+
async fn content_type_xml_as_text() {
404+
// Drive the implementation by using `hyper::Body` instead of
405+
// of `aws_lambda_events::encodings::Body`
406+
let response = Response::builder()
407+
.header(CONTENT_TYPE, "image/svg+xml")
408+
.body(HyperBody::from(SVG_LOGO.as_bytes()))
409+
.expect("unable to build http::Response");
410+
let response = response.into_response().await;
411+
412+
match response.body() {
413+
Body::Text(body) => assert_eq!(SVG_LOGO, body),
414+
_ => panic!("invalid body"),
415+
}
416+
assert_eq!(
417+
response
418+
.headers()
419+
.get(CONTENT_TYPE)
420+
.map(|h| h.to_str().expect("invalid header")),
421+
Some("image/svg+xml")
422+
)
423+
}
424+
425+
#[tokio::test]
426+
async fn content_type_custom_encoding_as_text() {
427+
// Drive the implementation by using `hyper::Body` instead of
428+
// of `aws_lambda_events::encodings::Body`
429+
let response = Response::builder()
430+
// this CONTENT-TYPE is not standard, and would yield a binary response
431+
.header(CONTENT_TYPE, "image/svg")
432+
.header(X_LAMBDA_HTTP_CONTENT_ENCODING, "text")
433+
.body(HyperBody::from(SVG_LOGO.as_bytes()))
434+
.expect("unable to build http::Response");
435+
let response = response.into_response().await;
436+
437+
match response.body() {
438+
Body::Text(body) => assert_eq!(SVG_LOGO, body),
439+
_ => panic!("invalid body"),
440+
}
441+
assert_eq!(
442+
response
443+
.headers()
444+
.get(CONTENT_TYPE)
445+
.map(|h| h.to_str().expect("invalid header")),
446+
Some("image/svg")
447+
)
448+
}
391449
}

lambda-http/tests/data/svg_logo.svg

Lines changed: 49 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)