1- //! ALB andAPI Gateway request types.
1+ //! ALB and API Gateway request types.
22//!
33//! Typically these are exposed via the `request_context`
44//! request extension method provided by [lambda_http::RequestExt](../trait.RequestExt.html)
55//!
6- use std:: { borrow:: Cow , collections:: HashMap , fmt, mem} ;
7-
86use http:: {
97 self ,
108 header:: { HeaderName , HeaderValue , HOST } ,
119 HeaderMap , Method , Request as HttpRequest ,
1210} ;
1311use serde:: de:: { Deserialize , Deserializer , Error as DeError , MapAccess , Visitor } ;
1412use serde_derive:: Deserialize ;
15- use serde_json:: Value ;
13+ use serde_json:: { error:: Error as JsonError , Value } ;
14+ use std:: { borrow:: Cow , collections:: HashMap , fmt, io:: Read , mem} ;
1615
1716use crate :: {
1817 body:: Body ,
@@ -322,12 +321,55 @@ impl<'a> From<LambdaRequest<'a>> for HttpRequest<Body> {
322321 }
323322}
324323
324+ /// Deserializes a Request from an IO stream of JSON.
325+ ///
326+ /// # Example
327+ ///
328+ /// ```rust,no_run
329+ /// use lambda_http::request::from_reader;
330+ /// use std::fs::File;
331+ /// use std::error::Error;
332+ ///
333+ /// fn main() -> Result<(), Box<dyn Error>> {
334+ /// let request = from_reader(
335+ /// File::open("path/to/request.json")?
336+ /// )?;
337+ /// Ok(println!("{:#?}", request))
338+ /// }
339+ /// ```
340+ pub fn from_reader < R > ( rdr : R ) -> Result < crate :: Request , JsonError >
341+ where
342+ R : Read ,
343+ {
344+ serde_json:: from_reader ( rdr) . map ( LambdaRequest :: into)
345+ }
346+
347+ /// Deserializes a Request from a string of JSON text.
348+ ///
349+ /// # Example
350+ ///
351+ /// ```rust,no_run
352+ /// use lambda_http::request::from_str;
353+ /// use std::fs::File;
354+ /// use std::error::Error;
355+ ///
356+ /// fn main() -> Result<(), Box<dyn Error>> {
357+ /// let request = from_str(
358+ /// r#"{ ...raw json here... }"#
359+ /// )?;
360+ /// Ok(println!("{:#?}", request))
361+ /// }
362+ /// ```
363+ pub fn from_str ( s : & str ) -> Result < crate :: Request , JsonError > {
364+ serde_json:: from_str ( s) . map ( LambdaRequest :: into)
365+ }
366+
325367#[ cfg( test) ]
326368mod tests {
327369 use super :: * ;
328370 use crate :: RequestExt ;
329371 use serde_json;
330- use std:: collections:: HashMap ;
372+ use std:: { collections:: HashMap , fs :: File } ;
331373
332374 #[ test]
333375 fn requests_convert ( ) {
@@ -345,12 +387,21 @@ mod tests {
345387 assert_eq ! ( expected. method( ) , actual. method( ) ) ;
346388 }
347389
390+ #[ test]
391+ fn deserializes_apigw_request_events_from_readables ( ) {
392+ // from the docs
393+ // https://docs.aws.amazon.com/lambda/latest/dg/eventsources.html#eventsources-api-gateway-request
394+ // note: file paths are relative to the directory of the crate at runtime
395+ let result = from_reader ( File :: open ( "tests/data/apigw_proxy_request.json" ) . expect ( "expected file" ) ) ;
396+ assert ! ( result. is_ok( ) , format!( "event was not parsed as expected {:?}" , result) ) ;
397+ }
398+
348399 #[ test]
349400 fn deserializes_apigw_request_events ( ) {
350401 // from the docs
351402 // https://docs.aws.amazon.com/lambda/latest/dg/eventsources.html#eventsources-api-gateway-request
352403 let input = include_str ! ( "../tests/data/apigw_proxy_request.json" ) ;
353- let result = serde_json :: from_str :: < LambdaRequest < ' _ > > ( & input) ;
404+ let result = from_str ( input) ;
354405 assert ! ( result. is_ok( ) , format!( "event was not parsed as expected {:?}" , result) ) ;
355406 }
356407
@@ -359,7 +410,7 @@ mod tests {
359410 // from the docs
360411 // https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html#multi-value-headers
361412 let input = include_str ! ( "../tests/data/alb_request.json" ) ;
362- let result = serde_json :: from_str :: < LambdaRequest < ' _ > > ( & input) ;
413+ let result = from_str ( input) ;
363414 assert ! ( result. is_ok( ) , format!( "event was not parsed as expected {:?}" , result) ) ;
364415 }
365416
@@ -368,19 +419,18 @@ mod tests {
368419 // from docs
369420 // https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format
370421 let input = include_str ! ( "../tests/data/apigw_multi_value_proxy_request.json" ) ;
371- let result = serde_json :: from_str :: < LambdaRequest < ' _ > > ( & input) ;
422+ let result = from_str ( input) ;
372423 assert ! (
373424 result. is_ok( ) ,
374425 format!( "event is was not parsed as expected {:?}" , result)
375426 ) ;
376- let apigw = result. unwrap ( ) ;
377- assert ! ( !apigw. query_string_parameters. is_empty( ) ) ;
378- assert ! ( !apigw. multi_value_query_string_parameters. is_empty( ) ) ;
379- let actual = HttpRequest :: from ( apigw) ;
427+ let unwrapped = result. unwrap ( ) ;
428+
429+ assert ! ( !unwrapped. query_string_parameters( ) . is_empty( ) ) ;
380430
381431 // test RequestExt#query_string_parameters does the right thing
382432 assert_eq ! (
383- actual . query_string_parameters( ) . get_all( "multivalueName" ) ,
433+ unwrapped . query_string_parameters( ) . get_all( "multivalueName" ) ,
384434 Some ( vec![ "you" , "me" ] )
385435 ) ;
386436 }
@@ -390,19 +440,17 @@ mod tests {
390440 // from docs
391441 // https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format
392442 let input = include_str ! ( "../tests/data/alb_multi_value_request.json" ) ;
393- let result = serde_json :: from_str :: < LambdaRequest < ' _ > > ( & input) ;
443+ let result = from_str ( input) ;
394444 assert ! (
395445 result. is_ok( ) ,
396446 format!( "event is was not parsed as expected {:?}" , result)
397447 ) ;
398- let apigw = result. unwrap ( ) ;
399- assert ! ( !apigw. query_string_parameters. is_empty( ) ) ;
400- assert ! ( !apigw. multi_value_query_string_parameters. is_empty( ) ) ;
401- let actual = HttpRequest :: from ( apigw) ;
448+ let unwrapped = result. unwrap ( ) ;
449+ assert ! ( !unwrapped. query_string_parameters( ) . is_empty( ) ) ;
402450
403451 // test RequestExt#query_string_parameters does the right thing
404452 assert_eq ! (
405- actual . query_string_parameters( ) . get_all( "myKey" ) ,
453+ unwrapped . query_string_parameters( ) . get_all( "myKey" ) ,
406454 Some ( vec![ "val1" , "val2" ] )
407455 ) ;
408456 }
0 commit comments