1
- //! ALB andAPI Gateway request types.
1
+ //! ALB and API Gateway request types.
2
2
//!
3
3
//! Typically these are exposed via the `request_context`
4
4
//! request extension method provided by [lambda_http::RequestExt](../trait.RequestExt.html)
5
5
//!
6
- use std:: { borrow:: Cow , collections:: HashMap , fmt, mem} ;
7
-
8
6
use http:: {
9
7
self ,
10
8
header:: { HeaderName , HeaderValue , HOST } ,
11
9
HeaderMap , Method , Request as HttpRequest ,
12
10
} ;
13
11
use serde:: de:: { Deserialize , Deserializer , Error as DeError , MapAccess , Visitor } ;
14
12
use 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} ;
16
15
17
16
use crate :: {
18
17
body:: Body ,
@@ -322,12 +321,55 @@ impl<'a> From<LambdaRequest<'a>> for HttpRequest<Body> {
322
321
}
323
322
}
324
323
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
+
325
367
#[ cfg( test) ]
326
368
mod tests {
327
369
use super :: * ;
328
370
use crate :: RequestExt ;
329
371
use serde_json;
330
- use std:: collections:: HashMap ;
372
+ use std:: { collections:: HashMap , fs :: File } ;
331
373
332
374
#[ test]
333
375
fn requests_convert ( ) {
@@ -345,12 +387,21 @@ mod tests {
345
387
assert_eq ! ( expected. method( ) , actual. method( ) ) ;
346
388
}
347
389
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
+
348
399
#[ test]
349
400
fn deserializes_apigw_request_events ( ) {
350
401
// from the docs
351
402
// https://docs.aws.amazon.com/lambda/latest/dg/eventsources.html#eventsources-api-gateway-request
352
403
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) ;
354
405
assert ! ( result. is_ok( ) , format!( "event was not parsed as expected {:?}" , result) ) ;
355
406
}
356
407
@@ -359,7 +410,7 @@ mod tests {
359
410
// from the docs
360
411
// https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html#multi-value-headers
361
412
let input = include_str ! ( "../tests/data/alb_request.json" ) ;
362
- let result = serde_json :: from_str :: < LambdaRequest < ' _ > > ( & input) ;
413
+ let result = from_str ( input) ;
363
414
assert ! ( result. is_ok( ) , format!( "event was not parsed as expected {:?}" , result) ) ;
364
415
}
365
416
@@ -368,19 +419,18 @@ mod tests {
368
419
// from docs
369
420
// https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format
370
421
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) ;
372
423
assert ! (
373
424
result. is_ok( ) ,
374
425
format!( "event is was not parsed as expected {:?}" , result)
375
426
) ;
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( ) ) ;
380
430
381
431
// test RequestExt#query_string_parameters does the right thing
382
432
assert_eq ! (
383
- actual . query_string_parameters( ) . get_all( "multivalueName" ) ,
433
+ unwrapped . query_string_parameters( ) . get_all( "multivalueName" ) ,
384
434
Some ( vec![ "you" , "me" ] )
385
435
) ;
386
436
}
@@ -390,19 +440,17 @@ mod tests {
390
440
// from docs
391
441
// https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format
392
442
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) ;
394
444
assert ! (
395
445
result. is_ok( ) ,
396
446
format!( "event is was not parsed as expected {:?}" , result)
397
447
) ;
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( ) ) ;
402
450
403
451
// test RequestExt#query_string_parameters does the right thing
404
452
assert_eq ! (
405
- actual . query_string_parameters( ) . get_all( "myKey" ) ,
453
+ unwrapped . query_string_parameters( ) . get_all( "myKey" ) ,
406
454
Some ( vec![ "val1" , "val2" ] )
407
455
) ;
408
456
}
0 commit comments