77//! Create a type that conforms to the [`tower::Service`] trait. This type can
88//! then be passed to the the `lambda_runtime::run` function, which launches
99//! and runs the Lambda runtime.
10- use hyper:: client:: { connect:: Connection , HttpConnector } ;
10+ use hyper:: {
11+ client:: { connect:: Connection , HttpConnector } ,
12+ http:: Request ,
13+ Body ,
14+ } ;
1115use lambda_runtime_api_client:: Client ;
1216use serde:: { Deserialize , Serialize } ;
13- use std:: { convert:: TryFrom , env, fmt, future:: Future , panic} ;
17+ use std:: {
18+ convert:: TryFrom ,
19+ env,
20+ fmt:: { self , Debug , Display } ,
21+ future:: Future ,
22+ panic,
23+ } ;
1424use tokio:: io:: { AsyncRead , AsyncWrite } ;
1525use tokio_stream:: { Stream , StreamExt } ;
1626pub use tower:: { self , service_fn, Service } ;
@@ -24,7 +34,6 @@ mod simulated;
2434mod types;
2535
2636use requests:: { EventCompletionRequest , EventErrorRequest , IntoRequest , NextEventRequest } ;
27- use types:: Diagnostic ;
2837pub use types:: { Context , LambdaEvent } ;
2938
3039/// Error type that lambdas may result in
@@ -121,12 +130,20 @@ where
121130
122131 let ctx: Context = Context :: try_from ( parts. headers ) ?;
123132 let ctx: Context = ctx. with_config ( config) ;
124- let body = serde_json :: from_slice ( & body ) ? ;
133+ let request_id = & ctx . request_id . clone ( ) ;
125134
126135 let xray_trace_id = & ctx. xray_trace_id . clone ( ) ;
127136 env:: set_var ( "_X_AMZN_TRACE_ID" , xray_trace_id) ;
128137
129- let request_id = & ctx. request_id . clone ( ) ;
138+ let body = match serde_json:: from_slice ( & body) {
139+ Ok ( body) => body,
140+ Err ( err) => {
141+ let req = build_event_error_request ( request_id, err) ?;
142+ client. call ( req) . await . expect ( "Unable to send response to Runtime APIs" ) ;
143+ return Ok ( ( ) ) ;
144+ }
145+ } ;
146+
130147 let req = match handler. ready ( ) . await {
131148 Ok ( handler) => {
132149 let task =
@@ -141,48 +158,23 @@ where
141158 }
142159 . into_req ( )
143160 }
144- Err ( err) => {
145- error ! ( "{:?}" , err) ; // logs the error in CloudWatch
146- EventErrorRequest {
147- request_id,
148- diagnostic : Diagnostic {
149- error_type : type_name_of_val ( & err) . to_owned ( ) ,
150- error_message : format ! ( "{}" , err) , // returns the error to the caller via Lambda API
151- } ,
152- }
153- . into_req ( )
154- }
161+ Err ( err) => build_event_error_request ( request_id, err) ,
155162 } ,
156163 Err ( err) => {
157164 error ! ( "{:?}" , err) ;
158- EventErrorRequest {
159- request_id,
160- diagnostic : Diagnostic {
161- error_type : type_name_of_val ( & err) . to_owned ( ) ,
162- error_message : if let Some ( msg) = err. downcast_ref :: < & str > ( ) {
163- format ! ( "Lambda panicked: {}" , msg)
164- } else {
165- "Lambda panicked" . to_string ( )
166- } ,
167- } ,
168- }
169- . into_req ( )
165+ let error_type = type_name_of_val ( & err) ;
166+ let msg = if let Some ( msg) = err. downcast_ref :: < & str > ( ) {
167+ format ! ( "Lambda panicked: {}" , msg)
168+ } else {
169+ "Lambda panicked" . to_string ( )
170+ } ;
171+ EventErrorRequest :: new ( request_id, error_type, & msg) . into_req ( )
170172 }
171173 }
172174 }
173- Err ( err) => {
174- error ! ( "{:?}" , err) ; // logs the error in CloudWatch
175- EventErrorRequest {
176- request_id,
177- diagnostic : Diagnostic {
178- error_type : type_name_of_val ( & err) . to_owned ( ) ,
179- error_message : format ! ( "{}" , err) , // returns the error to the caller via Lambda API
180- } ,
181- }
182- . into_req ( )
183- }
184- } ;
185- let req = req?;
175+ Err ( err) => build_event_error_request ( request_id, err) ,
176+ } ?;
177+
186178 client. call ( req) . await . expect ( "Unable to send response to Runtime APIs" ) ;
187179 }
188180 Ok ( ( ) )
@@ -247,6 +239,17 @@ fn type_name_of_val<T>(_: T) -> &'static str {
247239 std:: any:: type_name :: < T > ( )
248240}
249241
242+ fn build_event_error_request < T > ( request_id : & str , err : T ) -> Result < Request < Body > , Error >
243+ where
244+ T : Display + Debug ,
245+ {
246+ error ! ( "{:?}" , err) ; // logs the error in CloudWatch
247+ let error_type = type_name_of_val ( & err) ;
248+ let msg = format ! ( "{}" , err) ;
249+
250+ EventErrorRequest :: new ( request_id, error_type, & msg) . into_req ( )
251+ }
252+
250253#[ cfg( test) ]
251254mod endpoint_tests {
252255 use crate :: {
@@ -431,8 +434,8 @@ mod endpoint_tests {
431434 let req = EventErrorRequest {
432435 request_id : "156cb537-e2d4-11e8-9b34-d36013741fb9" ,
433436 diagnostic : Diagnostic {
434- error_type : "InvalidEventDataError" . to_string ( ) ,
435- error_message : "Error parsing event data" . to_string ( ) ,
437+ error_type : "InvalidEventDataError" ,
438+ error_message : "Error parsing event data" ,
436439 } ,
437440 } ;
438441 let req = req. into_req ( ) ?;
0 commit comments