7
7
//! Create a type that conforms to the [`tower::Service`] trait. This type can
8
8
//! then be passed to the the `lambda_runtime::run` function, which launches
9
9
//! 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
+ } ;
11
15
use lambda_runtime_api_client:: Client ;
12
16
use 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
+ } ;
14
24
use tokio:: io:: { AsyncRead , AsyncWrite } ;
15
25
use tokio_stream:: { Stream , StreamExt } ;
16
26
pub use tower:: { self , service_fn, Service } ;
@@ -24,7 +34,6 @@ mod simulated;
24
34
mod types;
25
35
26
36
use requests:: { EventCompletionRequest , EventErrorRequest , IntoRequest , NextEventRequest } ;
27
- use types:: Diagnostic ;
28
37
pub use types:: { Context , LambdaEvent } ;
29
38
30
39
/// Error type that lambdas may result in
@@ -121,12 +130,20 @@ where
121
130
122
131
let ctx: Context = Context :: try_from ( parts. headers ) ?;
123
132
let ctx: Context = ctx. with_config ( config) ;
124
- let body = serde_json :: from_slice ( & body ) ? ;
133
+ let request_id = & ctx . request_id . clone ( ) ;
125
134
126
135
let xray_trace_id = & ctx. xray_trace_id . clone ( ) ;
127
136
env:: set_var ( "_X_AMZN_TRACE_ID" , xray_trace_id) ;
128
137
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
+
130
147
let req = match handler. ready ( ) . await {
131
148
Ok ( handler) => {
132
149
let task =
@@ -141,48 +158,23 @@ where
141
158
}
142
159
. into_req ( )
143
160
}
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) ,
155
162
} ,
156
163
Err ( err) => {
157
164
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 ( )
170
172
}
171
173
}
172
174
}
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
+
186
178
client. call ( req) . await . expect ( "Unable to send response to Runtime APIs" ) ;
187
179
}
188
180
Ok ( ( ) )
@@ -247,6 +239,17 @@ fn type_name_of_val<T>(_: T) -> &'static str {
247
239
std:: any:: type_name :: < T > ( )
248
240
}
249
241
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
+
250
253
#[ cfg( test) ]
251
254
mod endpoint_tests {
252
255
use crate :: {
@@ -431,8 +434,8 @@ mod endpoint_tests {
431
434
let req = EventErrorRequest {
432
435
request_id : "156cb537-e2d4-11e8-9b34-d36013741fb9" ,
433
436
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" ,
436
439
} ,
437
440
} ;
438
441
let req = req. into_req ( ) ?;
0 commit comments