From 923db22ef3b98c0d1d56a8e3f27a7de4c6fbbf20 Mon Sep 17 00:00:00 2001 From: Mustafa Zaki Assagaf Date: Mon, 5 Dec 2022 12:06:06 +0700 Subject: [PATCH] Added IntoResponse implementation for (StatusCode, IntoResponse) --- lambda-http/src/response.rs | 117 +++++++++++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 2 deletions(-) diff --git a/lambda-http/src/response.rs b/lambda-http/src/response.rs index b174f98e..5a5f3e9f 100644 --- a/lambda-http/src/response.rs +++ b/lambda-http/src/response.rs @@ -11,7 +11,7 @@ use aws_lambda_events::encodings::Body; use encoding_rs::Encoding; use http::header::CONTENT_ENCODING; use http::HeaderMap; -use http::{header::CONTENT_TYPE, Response}; +use http::{header::CONTENT_TYPE, Response, StatusCode}; use http_body::Body as HttpBody; use hyper::body::to_bytes; use mime::{Mime, CHARSET}; @@ -179,6 +179,71 @@ impl IntoResponse for serde_json::Value { } } +impl IntoResponse for (StatusCode, String) { + fn into_response(self) -> ResponseFuture { + let (status, body) = self; + Box::pin(ready( + Response::builder() + .status(status) + .body(Body::from(body)) + .expect("unable to build http::Response"), + )) + } +} + +impl IntoResponse for (StatusCode, &str) { + fn into_response(self) -> ResponseFuture { + let (status, body) = self; + Box::pin(ready( + Response::builder() + .status(status) + .body(Body::from(body)) + .expect("unable to build http::Response"), + )) + } +} + +impl IntoResponse for (StatusCode, &[u8]) { + fn into_response(self) -> ResponseFuture { + let (status, body) = self; + Box::pin(ready( + Response::builder() + .status(status) + .body(Body::from(body)) + .expect("unable to build http::Response"), + )) + } +} + +impl IntoResponse for (StatusCode, Vec) { + fn into_response(self) -> ResponseFuture { + let (status, body) = self; + Box::pin(ready( + Response::builder() + .status(status) + .body(Body::from(body)) + .expect("unable to build http::Response"), + )) + } +} + +impl IntoResponse for (StatusCode, serde_json::Value) { + fn into_response(self) -> ResponseFuture { + let (status, body) = self; + Box::pin(async move { + Response::builder() + .status(status) + .header(CONTENT_TYPE, "application/json") + .body( + serde_json::to_string(&body) + .expect("unable to serialize serde_json::Value") + .into(), + ) + .expect("unable to build http::Response") + }) + } +} + pub type ResponseFuture = Pin> + Send>>; pub trait ConvertBody { @@ -269,7 +334,7 @@ mod tests { use super::{Body, IntoResponse, LambdaResponse, RequestOrigin, X_LAMBDA_HTTP_CONTENT_ENCODING}; use http::{ header::{CONTENT_ENCODING, CONTENT_TYPE}, - Response, + Response, StatusCode, }; use hyper::Body as HyperBody; use serde_json::{self, json}; @@ -310,6 +375,54 @@ mod tests { } } + #[tokio::test] + async fn json_with_status_code_into_response() { + let response = (StatusCode::CREATED, json!({ "hello": "lambda"})).into_response().await; + match response.body() { + Body::Text(json) => assert_eq!(json, r#"{"hello":"lambda"}"#), + _ => panic!("invalid body"), + } + match response.status() { + StatusCode::CREATED => (), + _ => panic!("invalid status code"), + } + + assert_eq!( + response + .headers() + .get(CONTENT_TYPE) + .map(|h| h.to_str().expect("invalid header")), + Some("application/json") + ) + } + + #[tokio::test] + async fn text_with_status_code_into_response() { + let response = (StatusCode::CREATED, "text").into_response().await; + + match response.status() { + StatusCode::CREATED => (), + _ => panic!("invalid status code"), + } + match response.body() { + Body::Text(text) => assert_eq!(text, "text"), + _ => panic!("invalid body"), + } + } + + #[tokio::test] + async fn bytes_with_status_code_into_response() { + let response = (StatusCode::CREATED, "text".as_bytes()).into_response().await; + match response.status() { + StatusCode::CREATED => (), + _ => panic!("invalid status code"), + } + match response.body() { + Body::Binary(data) => assert_eq!(data, "text".as_bytes()), + _ => panic!("invalid body"), + } + } + #[tokio::test] async fn content_encoding_header() { // Drive the implementation by using `hyper::Body` instead of