简体   繁体   中英

Throw errors from AWS Lambda through API Gateway with Lambda Proxy Integration

I have a basic AWS Lambda Function (Java 8) that either returns a successful message or an error. I want it to throw an error so that the actual Lambda function fails. However, I can't figure out how to "pass" this error object from the lambda function, through the API gateway, to the client. I've been trying to change the Gateway Responses, but no luck so far.

Because I need Lambda Proxy integration enabled, I haven't been successful. I've read through a guide on error handling , and many like it, but they all seem to have Lambda Proxy integration turned off.

My code:

package com.amazonaws.lambda.demo;

import java.util.HashMap;
import java.util.Map;

import org.json.JSONObject;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;

public class LambdaFunctionHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {

      @Override
      public APIGatewayProxyResponseEvent handleRequest( APIGatewayProxyRequestEvent input, Context context ) {
          APIGatewayProxyResponseEvent response = getSuccessResponse();

          // Fake some error happening that causes a runtime exception
          Map<String, Object> errorObj = getErrorObjectMap(context);
          JSONObject json = new JSONObject(errorObj);
          throw new RuntimeException(json.toString());
          //return response;

      }

      private APIGatewayProxyResponseEvent getSuccessResponse() {

            Map<String, String> headers = new HashMap<>();
            headers.put("Content-type", "text/plain");

            APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent()
                    .withStatusCode(200)
                    .withHeaders(headers)
                    .withBody("Success!")
                    .withIsBase64Encoded(Boolean.FALSE);



            return response;
      }

      private Map<String, Object> getErrorObjectMap(Context context){
            Map<String, Object> errorPayload = new HashMap<>();
            errorPayload.put("errorType", "BadRequest");
            errorPayload.put("httpStatus", 400);
            errorPayload.put("requestId", context.getAwsRequestId());
            errorPayload.put("message", "An unknown error has occurred. Please try again.");

            return errorPayload;
      }
}

I've tried changing the Default 4XX Gateway Response, as well as all of the other ones, to a custom message. However, it did not work. I still just get the {"message": "Internal server error"} message.

Because the request is proxied, I can't add templates in the Integration Response. Therefore, I'm not sure how to handle these errors. For now, I just return a normal response object. This works, but the Lambda function doesn't know that it failed.

Map<String, String> headers = new HashMap<>();
headers.put("Content-type", "text/plain");

APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent()
                    .withStatusCode(400)
                    .withHeaders(headers)
                    .withBody("Error!")
                    .withIsBase64Encoded(Boolean.FALSE);

How can I throw an error in the lambda function and handle it in the API gateway so that a custom message is sent to the client?

Returning error responses work differently when using Lambda Proxy integration . You don't throw an exception, but return a Map that contains the exception information.

If you have Proxy Integration enabled and you throw an exception, your Lambda function will be assumed to have failed unexpectedly (hence the error 500 you were receiving).

Try this code:

package org.example.basicapp;

import java.util.HashMap;
import java.util.Map;

public class LambdaFunctionHandler {

    public static Map<String, Object> handleRequest(final Map<String, Object> request) {

        final Map<String, Object> requestContext = (Map) request.get("requestContext");

        final Map<String, Object> responseHeaders = new HashMap<>();
        responseHeaders.put("x-OriginalAwsRequestId", requestContext.get("requestId"));

        final Map<String, Object> responseMap = new HashMap<>();
        responseMap.put("statusCode", 400);
        responseMap.put("headers", responseHeaders);
        responseMap.put("body", "An unknown error has occurred. Please try again.");
        return responseMap;
    }
}

Which will show this when tested in API Gateway:

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM