2

My Lambda-backed API Gateway endpoint always returns 200 regardless of integration responses.

I have a rather simple GET endpoint:

    public void process(InputStream inputStream, OutputStream outputStream) throws IOException {
        Tenant tenant = tenantsDao.getTenant(inputStream);

        if (tenant != null) {
            this.getObjectMapper().writerWithView(Tenant.TenantData.class).writeValue(outputStream, tenant);
        } else {
            throw new ApiKeyNotFoundException("API key not found.");
        }
    }

This correctly prints the error when I execute it via CURL:

$ curl https://<my_api_url>/keys/foo -v
…
< HTTP/2 200 
…
{"errorMessage":"API key not found.","errorType":"…"}

Even though I have the integration response mapping set:

    ApiMethodGetKeysApiKey:
        Type: "AWS::ApiGateway::Method"
        Properties:
            RestApiId: !Ref "ApiGatewayV1"
            ResourceId: !Ref "ApiResourceKeysApiKey"
            HttpMethod: "GET"
            AuthorizationType: "CUSTOM"
            AuthorizerId: !Ref "ApiAuthorizerV1"
            RequestValidatorId: !Ref "ParametersOnlyValidator"
            RequestParameters:
                method.request.header.Authorization: true
                method.request.path.apiKey: true
            MethodResponses:
                -
                    StatusCode: 200
                -
                    StatusCode: 404
            Integration:
                Type: "AWS"
                IntegrationHttpMethod: "POST"
                Uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${!stageVariables.KeyFetchingTarget}"
                Credentials: !GetAtt "ApiGatewayRole.Arn"
                RequestTemplates:
                    application/json: |
                        {
                            "tenantId": "$context.authorizer.tenantId",
                            "apiKey": "$input.params('apiKey')"
                        }
                IntegrationResponses:
                    -
                        StatusCode: 200
                    -
                        StatusCode: 404
                        SelectionPattern: ".*API key not found.*"
                        ResponseTemplates:
                            application/json: |
                                {
                                    "message": "$input.path('$.errorMessage')"
                                }
                PassthroughBehavior: "NEVER"

Am I missing something?

API Gateway execution logs shows that the Lambda error header is set properly:

(2f8d1403-be70-11e9-a7ce-dd90ab730381) Endpoint response headers: {Date=Wed, 14 Aug 2019 08:47:45 GMT, Content-Type=application/json, Content-Length=720, Connection=keep-alive, x-amzn-RequestId=1f731b7f-5f10-4c3d-87b1-b879379d7d5f, X-Amz-Function-Error=Unhandled, x-amzn-Remapped-Content-Length=0, X-Amz-Executed-Version=$LATEST, X-Amzn-Trace-Id=root=1-5d53cab1-6b333258463add60633ec5a8;parent=4013ac81631b59eb;sampled=1}
(2f8d1403-be70-11e9-a7ce-dd90ab730381) Endpoint response body before transformations:
{
    "errorMessage": "API key not found.",
    "errorType": …

1 Answer 1

2

The issue was resolved with assistance of AWS support team. The issue was, that if we format integration endpoint like that API Gateway doesn't recognize that it's a Lambda and handles response in different way (falls back to generic AWS integration).

Proper format of integration URI should be:

Uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${!stageVariables.KeyFetchingTarget}/invocations"

But it's not the end of the story - once the endpoint switches to this "mode", it got stuck in it, and it was not possible to set any kind of integration for error response handling. This is why debugging was so difficult.

Thus, if you fall into such issue you need to remove the endpoint and re-create it.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.