2

I have a simple Node.JS lambda which looks like this:

module.exports = async ({ req, utils }) => {
  return {
    statusCode: 200,
    headers: {
      foo: "bar"
    },
    body: "hello"
  };
});

It's setup to be called via a URL, so it goes through API Gateway (set to Lambda proxy). When I hit that URL I can see the correct body response but the custom headers are non-existant.

I thought maybe API Gateway is stripping them out or something, so I executed the Lambda via API Gateway..

Fri Jun 14 16:25:52 UTC 2019 : Starting execution for request: 13bd0dc7-8ec1-11e9-853f-a52b9bf360d6
Fri Jun 14 16:25:52 UTC 2019 : HTTP Method: GET, Resource Path: /track
Fri Jun 14 16:25:52 UTC 2019 : Method request path: {}
Fri Jun 14 16:25:52 UTC 2019 : Method request query string: {}
Fri Jun 14 16:25:52 UTC 2019 : Method request headers: {}
Fri Jun 14 16:25:52 UTC 2019 : Method request body before transformations: 
Fri Jun 14 16:25:52 UTC 2019 : Endpoint request headers: {x-amzn-lambda-integration-tag=13bd0dc7-8ec1-11e9-853f-a52b9bf360d6, Authorization=************************************************************************************************************************************************************************************************************************************************************************************************************************b35dc2, X-Amz-Date=20190614T162552Z, x-amzn-apigateway-api-id=eus1xpfhe4, X-Amz-Source-Arn=arn:aws:execute-api:eu-west-1:062996805340:eus1xpfhe4/test-invoke-stage/GET/track, Accept=application/json, User-Agent=AmazonAPIGateway_eus1xpfhe4, X-Amz-Security-Token=AgoJb3JpZ2luX2VjEMj//////////wEaCWV1LXdlc3QtMSJHMEUCIQCKh6FFu3duNK7z1dv4SYc+caB0P1dOM75UrjhkjnrApgIgfRSCzXisBuGtn9dSig7QDTPZ6xGL+LL6SyA3sGIAMyAq4wMI8f//////////ARAAGgw2MzExNDQwMDIwOTkiDHQ5JmnY3dq4QglpBCq3A1qg7BjxNgcFxlDIr72sxDQFixgdhM+DUh6gOp3MGnao24FBd7mQVNH7jcd2hzsOTpA2TQSZFtpUCY+0TSHZqAumfodN9k4tywe5uPqFora1e7zTXadG6CcRFYf/XkULirU8yirZ7ct [TRUNCATED]
Fri Jun 14 16:25:52 UTC 2019 : Endpoint request body after transformations: {"resource":"/track","path":"/track","httpMethod":"GET","headers":null,"multiValueHeaders":null,"queryStringParameters":null,"multiValueQueryStringParameters":null,"pathParameters":null,"stageVariables":null,"requestContext":{"path":"/track","accountId":"062996805340","resourceId":"hzxltu","stage":"test-invoke-stage","domainPrefix":"testPrefix","requestId":"13bd0dc7-8ec1-11e9-853f-a52b9bf360d6","identity":{"cognitoIdentityPoolId":null,"cognitoIdentityId":null,"apiKey":"test-invoke-api-key","principalOrgId":null,"cognitoAuthenticationType":null,"userArn":"arn:aws:iam::062996805340:user/richard","apiKeyId":"test-invoke-api-key-id","userAgent":"aws-internal/3 aws-sdk-java/1.11.563 Linux/4.9.137-0.1.ac.218.74.329.metal1.x86_64 OpenJDK_64-Bit_Server_VM/25.212-b03 java/1.8.0_212 vendor/Oracle_Corporation","accountId":"062996805340","caller":"AIDAJ44A63SBN65HTZQRC","sourceIp":"test-invoke-source-ip","accessKey":"ASIAQ5KXG63OHN7V2FAY","cognitoAuthenticationProvider":null," [TRUNCATED]
Fri Jun 14 16:25:52 UTC 2019 : Sending request to https://lambda.eu-west-1.amazonaws.com/2015-03-31/functions/arn:aws:lambda:eu-west-1:062996805340:function:analytics-api-development-track/invocations
Fri Jun 14 16:25:53 UTC 2019 : Received response. Status: 200, Integration latency: 859 ms
Fri Jun 14 16:25:53 UTC 2019 : Endpoint response headers: {Date=Fri, 14 Jun 2019 16:25:53 GMT, Content-Type=application/json, Content-Length=166, Connection=keep-alive, x-amzn-RequestId=910277df-74e9-4c94-bc38-062c112a6c87, x-amzn-Remapped-Content-Length=0, X-Amz-Executed-Version=$LATEST, X-Amzn-Trace-Id=root=1-5d03ca90-488f69c02c1ba617bfcd6963;sampled=0}
Fri Jun 14 16:25:53 UTC 2019 : Endpoint response body before transformations: {"statusCode":200,"headers":{"Access-Control-Allow-Origin":"*","Access-Control-Allow-Credentials":"true","Access-Control-Allow-Headers":"content-type"},"body":"\"\""}
Fri Jun 14 16:25:53 UTC 2019 : Method response body after transformations: ""
Fri Jun 14 16:25:53 UTC 2019 : Method response headers: {Access-Control-Allow-Origin=*, Access-Control-Allow-Credentials=true, Access-Control-Allow-Headers=content-type, X-Amzn-Trace-Id=Root=1-5d03ca90-488f69c02c1ba617bfcd6963;Sampled=0}
Fri Jun 14 16:25:53 UTC 2019 : Successfully completed execution
Fri Jun 14 16:25:53 UTC 2019 : Method completed with status: 200

Response headers:

{"Access-Control-Allow-Origin":"*","Access-Control-Allow-Credentials":"true","Access-Control-Allow-Headers":"content-type","X-Amzn-Trace-Id":"Root=1-5d03ca90-488f69c02c1ba617bfcd6963;Sampled=0"}

Any tips? I have no idea why the headers are getting stripped out and replaced with access control related ones.

Thanks!

EDIT:

I've now pinned it down to the Lambda instead of API Gateway. Somehow the output from the Lambda is this..

{
  "statusCode": 200,
  "headers": {
    "Access-Control-Allow-Origin": "*",
    "Access-Control-Allow-Credentials": "true",
    "Access-Control-Allow-Headers": "content-type"
  },
  "body": "\"hello\""
}
richwol
  • 1,065
  • 2
  • 11
  • 24
  • Possible duplicate https://stackoverflow.com/questions/43190935/setting-http-response-header-from-aws-lambda – Mark B Jun 14 '19 at 17:18
  • I don't think it's a duplicate, it's just describing the output format the Lambda should be if lambda proxy is enabled. The example output in the accepted answer is very similar to the one I have created above – richwol Jun 14 '19 at 17:22
  • The fact that API Gateway is returning different headers, and in particular adding CORS headers, makes me think you might not actually be using the `Proxy` integration type. Can you double check that? – Mark B Jun 14 '19 at 17:31
  • Yep, it's set to Type: LAMBDA_PROXY :( – richwol Jun 14 '19 at 17:34
  • Your function parameters look wrong. There should be 3, Event, Context and Callback. You should call callback(null, ), and then return nothing to exit the function. That should correctly set the headers I believe. – BParker Jun 14 '19 at 22:02
  • @BParker things are done differently when you use an `async` handler function. You return the response or a promise that will render the response, and don't use a callback. – Michael - sqlbot Jun 14 '19 at 22:46

0 Answers0