1
- use error:: { ApiError , RuntimeApiError } ;
1
+ use error:: { ApiError , ErrorResponse , RuntimeApiError } ;
2
2
use hyper:: {
3
3
client:: HttpConnector ,
4
4
header:: { self , HeaderMap , HeaderValue } ,
@@ -11,6 +11,8 @@ use tokio::runtime::Runtime;
11
11
12
12
const RUNTIME_API_VERSION : & str = "2018-06-01" ;
13
13
const API_CONTENT_TYPE : & str = "application/json" ;
14
+ const API_ERROR_CONTENT_TYPE : & str = "application/vnd.aws.lambda.error+json" ;
15
+ const RUNTIME_ERROR_HEADER : & str = "Lambda-Runtime-Function-Error-Type" ;
14
16
15
17
/// Enum of the headers returned by Lambda's `/next` API call.
16
18
pub enum LambdaHeaders {
@@ -141,7 +143,8 @@ impl RuntimeClient {
141
143
let uri = format ! (
142
144
"http://{}/{}/runtime/invocation/next" ,
143
145
self . endpoint, RUNTIME_API_VERSION
144
- ) . parse ( ) ?;
146
+ )
147
+ . parse ( ) ?;
145
148
trace ! ( "Polling for next event" ) ;
146
149
147
150
// We wait instead of processing the future asynchronously because AWS Lambda
@@ -203,7 +206,8 @@ impl RuntimeClient {
203
206
let uri: Uri = format ! (
204
207
"http://{}/{}/runtime/invocation/{}/response" ,
205
208
self . endpoint, RUNTIME_API_VERSION , request_id
206
- ) . parse ( ) ?;
209
+ )
210
+ . parse ( ) ?;
207
211
trace ! (
208
212
"Posting response for request {} to Runtime API. Response length {} bytes" ,
209
213
request_id,
@@ -250,14 +254,14 @@ impl RuntimeClient {
250
254
let uri: Uri = format ! (
251
255
"http://{}/{}/runtime/invocation/{}/error" ,
252
256
self . endpoint, RUNTIME_API_VERSION , request_id
253
- ) . parse ( ) ?;
257
+ )
258
+ . parse ( ) ?;
254
259
trace ! (
255
260
"Posting error to runtime API for request {}: {}" ,
256
261
request_id,
257
262
e. to_response( ) . error_message
258
263
) ;
259
- let err_body = serde_json:: to_vec ( & e. to_response ( ) ) . expect ( "Could not serialize error object" ) ;
260
- let req = self . get_runtime_post_request ( & uri, err_body) ;
264
+ let req = self . get_runtime_error_request ( & uri, & e. to_response ( ) ) ;
261
265
262
266
match self . http_client . request ( req) . wait ( ) {
263
267
Ok ( resp) => {
@@ -298,19 +302,19 @@ impl RuntimeClient {
298
302
. parse ( )
299
303
. expect ( "Could not generate Runtime URI" ) ;
300
304
error ! ( "Calling fail_init Runtime API: {}" , e. to_response( ) . error_message) ;
301
- let err_body = serde_json:: to_vec ( & e. to_response ( ) ) . expect ( "Could not serialize error object" ) ;
302
- let req = self . get_runtime_post_request ( & uri, err_body) ;
305
+ let req = self . get_runtime_error_request ( & uri, & e. to_response ( ) ) ;
303
306
304
- let resp = self
305
- . http_client
307
+ self . http_client
306
308
. request ( req)
309
+ . wait ( )
307
310
. map_err ( |e| {
308
311
error ! ( "Error while sending init failed message: {}" , e) ;
309
312
panic ! ( "Error while sending init failed message: {}" , e) ;
310
- } ) . map ( |resp| {
313
+ } )
314
+ . map ( |resp| {
311
315
info ! ( "Successfully sent error response to the runtime API: {:?}" , resp) ;
312
- } ) ;
313
- tokio :: spawn ( resp ) ;
316
+ } )
317
+ . expect ( "Could not complete init_fail request" ) ;
314
318
}
315
319
316
320
/// Returns the endpoint configured for this HTTP Runtime client.
@@ -339,6 +343,20 @@ impl RuntimeClient {
339
343
. unwrap ( )
340
344
}
341
345
346
+ fn get_runtime_error_request ( & self , uri : & Uri , e : & ErrorResponse ) -> Request < Body > {
347
+ let body = serde_json:: to_vec ( e) . expect ( "Could not turn error object into response JSON" ) ;
348
+ Request :: builder ( )
349
+ . method ( Method :: POST )
350
+ . uri ( uri. clone ( ) )
351
+ . header (
352
+ header:: CONTENT_TYPE ,
353
+ header:: HeaderValue :: from_static ( API_ERROR_CONTENT_TYPE ) ,
354
+ )
355
+ . header ( RUNTIME_ERROR_HEADER , HeaderValue :: from_static ( "RuntimeError" ) ) // TODO: We should add this code to the error object.
356
+ . body ( Body :: from ( body) )
357
+ . unwrap ( )
358
+ }
359
+
342
360
/// Creates an `EventContext` object based on the response returned by the Runtime
343
361
/// API `/next` endpoint.
344
362
///
@@ -383,7 +401,8 @@ impl RuntimeClient {
383
401
error ! ( "Response headers do not contain deadline header" ) ;
384
402
return Err ( ApiError :: new ( & format ! ( "Missing {} header" , LambdaHeaders :: Deadline ) ) ) ;
385
403
}
386
- } . parse :: < u128 > ( ) ?;
404
+ }
405
+ . parse :: < u128 > ( ) ?;
387
406
388
407
let mut ctx = EventContext {
389
408
aws_request_id,
0 commit comments