AWS Elastic Beanstalk Worker Can't Connect to SQS - amazon-web-services

I have a problem with AWS ElasticBeanstalk Worker with SQS. I have read many resources and do experiment about it but still can't connect the worker with SQS successfully.
The worker act as consumer is created using Node.js with Hapi. I have tested this script using CURL in my local computer and it works well.
var Hapi = require('hapi');
var Good = require('good');
var server = new Hapi.Server();
server.connection({
port: process.env.PORT || 3000
});
server.route({
method: 'POST',
path: '/hello',
handler: function (request, reply) {
console.log('CIHUUY response: ', request.payload);
reply();
}
});
server.register({
register: require('good'),
options: {
reporters: [{
reporter: require('good-console'),
events: { log: '*', response: '*' }
}]
}
}, function (err) {
if (err) {
console.error(err);
}
else {
server.start(function () {
console.info('Server started at ' + server.info.uri);
});
}
});
My IAM Policy for the worker
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "QueueAccess",
"Action": [
"sqs:ChangeMessageVisibility",
"sqs:DeleteMessage",
"sqs:ReceiveMessage",
"sqs:SendMessage"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Sid": "MetricsAccess",
"Action": [
"cloudwatch:PutMetricData"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
For queue, I set the permission to allow everybody to access it. I give it a name testingqueue
For worker configuration
I checked the log /var/log/nodejs/nodejs.log
^[[1;33mpost^[[0m /hello {} ^[[33m400^[[0m (2ms)
150701/094208.444, [response], http://ip-10-142-107-58:8081: ^[[1;33mpost^[[0m /hello {} ^[[33m400^[[0m (1ms)
150701/094208.773, [response], http://ip-10-142-107-58:8081: ^[[1;33mpost^[[0m /hello {} ^[[33m400^[[0m (2ms)
150701/094208.792, [response], http://ip-10-142-107-58:8081: ^[[1;33mpost^[[0m /hello {} ^[[33m400^[[0m (1ms)
150701/094208.882, [response], http://ip-10-142-107-58:8081: ^[[1;33mpost^[[0m /hello {} ^[[33m400^[[0m (1ms)
150701/094208.951, [response], http://ip-10-142-107-58:8081: ^[[1;33mpost^[[0m
I also checked the awssqsd log /var/log/aws-sqsd/default.log
2015-07-01T09:44:40Z http-err: 75704523-42de-40de-9f9f-8a59eb3fb332 (7324) 400 - 0.004
2015-07-01T09:44:40Z message: sent to %[http://localhost:80]
2015-07-01T09:44:40Z http-err: 59e2a75b-87f7-4833-8cde-11900d48a7c5 (3770) 400 - 0.007
2015-07-01T09:44:40Z message: sent to %[http://localhost:80]
2015-07-01T09:44:40Z http-err: e2acb4e0-1059-4dc7-9101-8d3e4c974108 (7035) 400 - 0.003
2015-07-01T09:44:40Z message: sent to %[http://localhost:80]
2015-07-01T09:44:40Z http-err: 04d2436a-0b1e-4a1f-8826-a2b30710f569 (9957) 400 - 0.005
I keep getting error 400. I'm curious why it can't connect.
Things I have done:
Queue is created and selected in worker configuration
Worker already use correct IAM policy
The HTTP Path is match, using /hello with POST method
Anyone maybe can help me here
Thank you

there is nothing wrong with your code. I just depoyed it to AWS with no problem.
/var/log/nodejs/nodejs.log
Server started at http://myIP:8081
CIHUUY response: { test: 'testvalue' }
151118/110150.862, [response], http://myIP:8081: [1;33mpost[0m /hello {} [32m200[0m (38ms)
/var/log/aws-sqsd/default.log
2015-11-18T10:58:38Z init: initializing aws-sqsd 2.0 (2015-02-18)
2015-11-18T10:58:39Z start: polling https://sqs.us-west-2.amazonaws.com/myaccountname/awseb-e-mnpfjxiump-stack-AWSEBWorkerQueue-1FPDK4Z8E3WRX
2015-11-18T11:01:50Z message: sent to %[http://localhost:80]
As you can see my test message was received. Only difference is can see is thah i have autogenerated queue, but that should not be a problem, because your logs shows that demon took message from queue and forwarded it. I use the same policy as you do for my worker.

Related

How can I enable CORS on AWS resources?

express server config:
app.use(
cors({
origin: "*",
methods: "GET,PUT,POST",
allowedHeaders: "*",
exposeHeaders: "*",
optionsSuccessStatus: 200,
})
);
//this fails as well
app.use(cors());
client side request:
let value= await axios({
url: "https://my.api.here.cloud/verifyGroup",
method: "post",
data: data.value,
});
Access to XMLHttpRequest at 'https://my.api.here.cloud/verifyGroup' from origin 'https://my.frontend.here.cloud' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I'm fairly confident it has something to do with AWS resources because in my local environment, these configs allow for cors but as soon as it's up on AWS, I'm getting blocked by cors.
I'm running an ECS Fargate service that's running a single task containing a frontend container and the backend container. Each of these containers has an ALB attached to them.
I came across this post here which gave me some hope, so I tried implementing it into my own solution but it still came up short.
my attempt at implementing the solution from the other post. This is what's being returned at an endpoint:
res.json({
headers: {
"Access-Content-Allow-Origin": "*",
},
statusCode: 200,
body: {
value: true,
},
});

Lambda sending notifications via pinpoint is very unreliable, how do I fix this?

I'm trying to send a GCM notification from an AWS lambda function.
I have two questions:
What permissions does the exection role require?
Is the behavioud described below the best I can expect from AWS notification, do I need to look at another service?
I've followed info from another question:
Send a notification by Lambda function with AWS Pinpoint
My lambda is as follows:
async function sendMessage() {
try {
const pinpoint = new AWS.Pinpoint();
let users = {};
users["---"] = {};
const params = {
ApplicationId: applicationId,
SendUsersMessageRequest: {
Users: users,
MessageConfiguration: {
'GCMMessage': {
Action: 'OPEN_APP',
Title: "Lambda User Msg",
SilentPush: false,
Body: "Lambda User Send Message Test"
}
}
}
};
console.log("Params:", params);
let rspnData = await pinpoint.sendUsersMessages(params).promise();
console.log("sendUsersMessages:rspnData:", rspnData);
} catch (err) {
console.log("sendMessage error:", err);
}
}
Can someone advise as to the minimal permissions required by the execution role of the lambda?
I've currently allowed everything pinpoint related, but would like
to be certain what should actually be allows?
2.
When I test the code from the AWS lambda code console I get the following execution log:
2022-02-11T08:57:26.446Z --- INFO SendMessage
2022-02-11T08:57:26.466Z --- INFO Params: { ApplicationId: '---',
SendUsersMessageRequest: {
Users: { '---': {} },
MessageConfiguration: { GCMMessage: [Object] } } } END RequestId:
There is no output from the sendUserMessage!
ASIDE: I've increased maximum execution time to 20secs, but this feels wrong!
Or I get an error of the form:
2022-02-11T09:38:32.721Z --- INFO sendMessage error: Error: Client network socket disconnected before secure TLS connection was established
at connResetException (internal/errors.js:639:14)
at TLSSocket.onConnectEnd (_tls_wrap.js:1570:19)
at TLSSocket.emit (events.js:412:35)
at TLSSocket.emit (domain.js:475:12)
at endReadableNT (internal/streams/readable.js:1334:12)
at processTicksAndRejections (internal/process/task_queues.js:82:21) {
code: 'TimeoutError',
path: null,
host: 'pinpoint.eu-west-2.amazonaws.com',
port: 443,
localAddress: undefined,
time: 2022-02-11T09:38:32.721Z,
region: 'eu-west-2',
hostname: 'pinpoint.eu-west-2.amazonaws.com',
retryable: true
}
END RequestId: ---
REPORT RequestId: --- Duration: 173.82 ms Billed Duration: 174 ms Memory Size: 128 MB Max Memory Used: 83 MB
Intermitently in the Cloudwatch log I get the following output:
2022-02-11T08:54:11.847Z --- INFO sendUsersMessages:rspnData: {
SendUsersMessageResponse: {
ApplicationId: '---',
RequestId: '---',
Result: { '---': [Object] }
}
}
indicating the notification was actually successfully sent!
On some occasions I get a notification in the app!
Usually very delayed!
If I use the same Id's via aws cli:
aws pinpoint send-users-messages --cli-input-json file://pinpoint-send-users-messages.json
I get a prompt notification, as expected!
Is this the best I can hope for from AWS send notifications, do I need to look at another
service, or am I doing something wrong?
In my case the lambda has the following role.
I don't know if it will be of any help, but please take a look.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents",
"logs:CreateLogGroup"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": "mobiletargeting:SendUsersMessages",
"Resource": "arn:aws:mobiletargeting:us-west-2:{your aws account id}:apps/{pinpoint project id}/messages"
},
{
"Effect": "Allow",
"Action": [
"mobiletargeting:GetEndpoint",
"mobiletargeting:UpdateEndpoint",
"mobiletargeting:PutEvents"
],
"Resource": "arn:aws:mobiletargeting:us-west-2:{your aws account id}:apps/{pinpoint project id}/endpoints/*"
}
]
}

API Gateway -> SQS HTTP POST MessageAttributes

I have an API gateway setup which sends to SQS which fires a Lambda, I am trying to pass message attributes to the SQS but when I hit the endpoint in postman I keep getting a 400 Bad Request.. what is the right way to send the attributes over a JSON POST body
here is body from postman (have tried a few options based on this link)
"message": "Message",
"MessageAttributes": {
"Name": "Name",
"Type": "String",
"Value": "my value"
}
}
Here is how API Gateway is configured
Incase someone stumbles on this later here is worked from the CDK side
let intergation = new apiGateway.CfnIntegration(this, 'Integration', {
apiId: props.httpApi.httpApiId,
payloadFormatVersion: '1.0',
integrationType: 'AWS_PROXY',
credentialsArn: apigwRole.roleArn,
integrationSubtype: 'SQS-SendMessage',
requestParameters: {
QueueUrl: sqsqueue.queueUrl,
MessageBody: '$request.body',
MessageAttributes: '$request.body.MessageAttributes'
}
})
new apiGateway.CfnRoute(this, 'Route', {
apiId: props.httpApi.httpApiId,
routeKey: apiGateway.HttpRouteKey.with('/url/foo', apiGateway.HttpMethod.POST).key,
target: `integrations/${intergation .ref}`
}).addDependsOn(intergation);
and the cloudformation
MessageBody: $request.body
MessageAttributes: $request.body.MessageAttribute
then in post man the POST body content type as application/json
{
"message": "Message",
"MessageAttributes": {
"Attributes": {
"DataType": "String",
"StringValue": "my value"
}
}
}
the lamba would log out both separate for each Record from the event body
Records: [
{
....
body: 'Message',
attributes: [Object],
messageAttributes: [Object]
}
]
}
the messageAttributes object from above:
{
Attributes: {
stringValue: 'my value',
stringListValues: [],
binaryListValues: [],
dataType: 'String'
}
}
This is using AWS API Gateway v2 HTTP API also

Adding SES as the destination in an AWS lambda function

After correctly creating a REST API trigger through API gateway and linking it with a lambda function, I am trying to add SES as the destination.
The purpose of the function would be to automatically forward messages received on a HTML contact form on a static website to an email address through SES service.
As per the caption I have created a lambda function I will show here below (just hid the domain and the email addresses for privacy).
var AWS = require('aws-sdk');
var ses = new AWS.SES();
var RECEIVER = 'XXX#gmail.com';
var SENDER = 'XXX#gmail.com';
var response = {
"isBase64Encoded": false,
"headers": { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': 'XXX.com'},
"statusCode": 200,
"body": "{\"result\": \"Success.\"}"
};
exports.handler = function (event, context) {
console.log('Received event:', event);
sendEmail(event, function (err, data) {
context.done(err, null);
});
};
function sendEmail (event, done) {
var params = {
Destination: {
ToAddresses: [
RECEIVER
]
},
Message: {
Body: {
Text: {
Data: 'name: ' + event.name + '\nphone: ' + event.phone + '\nemail: ' + event.email + '\ndesc: ' + event.desc,
Charset: 'UTF-8'
}
},
Subject: {
Data: 'Website Referral Form: ' + event.name,
Charset: 'UTF-8'
}
},
Source: SENDER
};
ses.sendEmail(params, done);
}
The relevant permissions to SES have been granted to the lambda function.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "ses:SendEmail",
"Resource": "*"
}
]
}
The testing of the function is indicated below:
Response
null
Function Logs
START RequestId: 765f6d27-9810-4d6c-a01b-a883eb429cd8 Version: $LATEST
2021-03-03T15:39:05.849Z 765f6d27-9810-4d6c-a01b-a883eb429cd8 INFO Received event: { key1: 'value1', key2: 'value2', key3: 'value3' }
END RequestId: 765f6d27-9810-4d6c-a01b-a883eb429cd8
REPORT RequestId: 765f6d27-9810-4d6c-a01b-a883eb429cd8 Duration: 928.32 ms Billed Duration: 929 ms Memory Size: 128 MB Max Memory Used: 87 MB Init Duration: 449.71 ms
Request ID
765f6d27-9810-4d6c-a01b-a883eb429cd8
Unfortunately, when I click on add destinations I cannot find the SES service to be selected.
The email address has already been validated in SES.
What else am I missing?
Thank you
SES isn't a supported destination. Lambda destinations are for sending the output of a Lambda function to another service, without writing code in the function for connecting directly to the service.
You don't need Lambda to send anything to an SES destination because you already sent the request directly in your code via ses.sendEmail().

CloudFormation API Gateway CORS issue access to XMLHttpRequest blocked

I'm trying to use CloudFormation to create an API Gateway but I have CORS issue with it.
Error on the front-end:
POST https://<>.execute-api.us-east-1.amazonaws.com/prod/<> 500
new:1 Access to XMLHttpRequest at '<>' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
The API is created without any issue and I even double check every single page on the console against the working API and find no differences in their Method Request, Integration Request, Integration Response and Method Response for all the methods (including the OPTIONS).
If I remove the resources created by the template and create them manually in the same API gateway then my code works as expected. I've tested with the localhost, front-end code in S3 bucket and PostMan, so I can verify that my front-end code, lambda functions and database are working correctly.
I understand that people have had this issue before but I haven't been able to find any answer that solves my issue.
Here's my template.
Please note that the "method.response.header.Access-Control-Allow-Origin": false actually creates the API with the same settings as the working one.
I also use the code from the correct answer for this question.
Yes, my OPTIONS request has the "Access-Control-Allow-Origin" header.
Update
Following dannymac's answer below. I got these:
I added console.log(event.requestContext); to my Lambda function (written in Node.js).
There are logs for Lambda when I test the function.
2019-06-27T20:07:03.118Z 462b93b2-9d4b-4ed3-bc04-f966fcd034cf Debug CORS issue. Request ID:
2019-06-27T20:07:03.118Z 462b93b2-9d4b-4ed3-bc04-f966fcd034cf undefined
It looks like there is no event.requestContext.
I selected Enable CloudWatch Logs-INFO and Enable Detailed CloudWatch Metrics with CloudWatch log role ARN*:arn:aws:iam::<ID>:role/ApiGatewayCloudWatchLogsRole (it's a role created by AWS) in the API Gateway settings.
However, there is no CloudWatch log for the API Gateway. There's a default log in CloudWatch - Log Groups: /aws/apigateway/welcome
Time (UTC +00:00)
2019-06-27
19:50:55
Cloudwatch logs enabled for API Gateway
It looks like the CloudWatch log didn't pick up the test from API Gateway.
This is what I got from testing the GET method in my API Gateway:
Response Body
{
"message": "Internal server error"
}
Response Headers
{}
Logs
Execution log for request 10d90173-9919-11e9-82e1-dd33dda3b9df
Thu Jun 27 20:20:54 UTC 2019 : Starting execution for request: 10d90173-9919-11e9-82e1-dd33dda3b9df
Thu Jun 27 20:20:54 UTC 2019 : HTTP Method: GET, Resource Path: /notes
Thu Jun 27 20:20:54 UTC 2019 : Method request path: {}
Thu Jun 27 20:20:54 UTC 2019 : Method request query string: {userid=<ID>}
Thu Jun 27 20:20:54 UTC 2019 : Method request headers: {}
Thu Jun 27 20:20:54 UTC 2019 : Method request body before transformations:
Thu Jun 27 20:20:54 UTC 2019 : Endpoint request URI: https://lambda.us-east-1.amazonaws.com/2015-03-31/functions/arn:aws:lambda:us-east-1:770402430649:function:test-api-gateway-2-LambdaFunction-1XDONAN3QIY9I/invocations
Thu Jun 27 20:20:54 UTC 2019 : Endpoint request headers: {x-amzn-lambda-integration-tag=... [TRUNCATED]
Thu Jun 27 20:20:54 UTC 2019 : Endpoint request body after transformations: {"resource":"/notes","path":"/notes","httpMethod":"GET","headers":null,"multiValueHeaders":null,"queryStringParameters":{"userid":"<USERID>"},"multiValueQueryStringParameters":{"userid":["<USERID>"]},"pathParameters":null,"stageVariables":null,"requestContext":{"path":"/notes","accountId":"<ID>"...,"identity":{"cognitoIdentityPoolId":null,"cognitoIdentityId":null,"apiKey":"test-invoke-api-key","principalOrgId":null,"cognitoAuthenticationType":null,"userArn":"<ARN>","apiKeyId":"test-invoke-api-key-id","userAgent":..."test [TRUNCATED]
Thu Jun 27 20:20:54 UTC 2019 : Sending request to https://lambda.us-east-1.amazonaws.com/2015-03-31/functions/arn:aws:lambda:us-east-1:<ID>:function:test-api-gateway-2-LambdaFunction-<STRING>/invocations
Thu Jun 27 20:20:54 UTC 2019 : Received response. Status: 403, Integration latency: 6 ms
Thu Jun 27 20:20:54 UTC 2019 : Endpoint response headers: {Date=Thu, 27 Jun 2019 20:20:54 GMT, Content-Length=130, Connection=keep-alive, x-amzn-RequestId=<ID>}
Thu Jun 27 20:20:54 UTC 2019 : Endpoint response body before transformations: <AccessDeniedException>
<Message>Unable to determine service/operation name to be authorized</Message>
</AccessDeniedException>
Thu Jun 27 20:20:54 UTC 2019 : Lambda invocation failed with status: 403. Lambda request id: feb22917-0dea-4f91-a274-fb6b85a69121
Thu Jun 27 20:20:54 UTC 2019 : Execution failed due to configuration error:
Thu Jun 27 20:20:54 UTC 2019 : Method completed with status: 500
I've also exported both the working and not working API Gateway in Swagger 2. The only difference is:
// working one:
"x-amazon-apigateway-any-method": {
"produces": [
"application/json"
],
"parameters": [
{
"name": "noteid",
"in": "path",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "200 response",
"schema": {
"$ref": "#/definitions/Empty"
}
}
},
"security": [
{
"mobile-notes-api-authorizer": []
}
]
}
// not working one:
"x-amazon-apigateway-any-method": {
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "200 response",
"schema": {
"$ref": "#/definitions/Empty"
}
}
},
"security": [
{
"test-api-gateway-2-authorizer": []
}
]
}
They both have:
"headers": {
"Access-Control-Allow-Origin": {
"type": "string"
},
"Access-Control-Allow-Methods": {
"type": "string"
},
"Access-Control-Allow-Headers": {
"type": "string"
}
}
I've tried to use the Swagger template in the Body of my API Gateway before but unable to solve the invalid authorizer issue.
I've figured out the issue. There are 2 main things:
The IntegrationHttpMethod for Lambda must be POST. I found the answer here.
The template didn't have AWS::Lambda::Permission that allows API Gateway to invoke Lambda function.
With the template, when you use AWS::Lambda::Permission, it will show the API as a trigger of your Lambda function.
However, if you manually create the API Gateway and link it with your Lambda function, it won't show API Gateway as a trigger but it still works.
So for the template I posted above, I needed to add these for it to work:
"LambdaPermission": {
"Type": "AWS::Lambda::Permission",
"Description": "Permission for API GateWay to invoke Lambda.",
"Properties": {
"Action": "lambda:invokeFunction",
"FunctionName": {
"Fn::GetAtt": [
"LambdaFunction",
"Arn"
]
},
"Principal": "apigateway.amazonaws.com",
"SourceArn": {
"Fn::Join": [
"",
[
"arn:aws:execute-api:",
{
"Ref": "AWS::Region"
},
":",
{
"Ref": "AWS::AccountId"
},
":",
{
"Ref": "ApiGateway"
},
"/*"
]
]
}
}
},
And edit method ANY to look like this
"methodNotesANY": {
"Type": "AWS::ApiGateway::Method",
"DependsOn": "LambdaPermission",
"Properties": {
"AuthorizationType": "COGNITO_USER_POOLS",
"AuthorizerId": {
"Ref": "GatewayAuthorizer"
},
"RestApiId": {
"Ref": "ApiGateway"
},
"ResourceId": {
"Ref": "resourceNotes"
},
"HttpMethod": "ANY",
"Integration": {
"Type": "AWS_PROXY",
"IntegrationHttpMethod": "POST",
"Uri": {
"Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaFunction.Arn}/invocations"
},
"IntegrationResponses": [{
"StatusCode": "200"
}]
},
"MethodResponses": [{
"ResponseModels": {
"application/json": "Empty"
},
"StatusCode": "200"
}]
}
},
My Best Guess: The POST to your ANY lambda function is failing during execution, and not setting the Access-Control-Allow-Origin header to * (or your domain). Anytime I get a 5XX error and a CORS error at the same time from a non-OPTIONS request, this is almost always the case for me.
Recommended Next Steps: Reproduce the error situation after adding debug logging to your Lambda source code, and turning on CloudWatch Logs in your API Gateway Rest API. You can do this by going to the API Gateway console, clicking on Stages > Prod > Logs/Tracing, then checking these two: Enable CloudWatch Logs (Log level: INFO), and Enable Detailed CloudWatch Metrics. Then you must "deploy" the changes in order for them to take effect. Do this by clicking the Actions button from your Rest API's Resources menu, and choosing Deploy API. I also recommend logging the extendedRequestId (an event property passed to your handler) from your Lambda function in order to tie the Lambda request to the API Gateway request: event.requestContext.extendedRequestId.
Example API Gateway logs:
(b66b3876-984b-11e9-95eb-dd93c7e40ca0) Extended Request Id: b5zpBGS3IAMFvqw=
(b66b3876-984b-11e9-95eb-dd93c7e40ca0) Verifying Usage Plan for request: b66b3876-984b-11e9-95eb-dd93c7e40ca0. API Key: API Stage: 1234567890/Prod
(b66b3876-984b-11e9-95eb-dd93c7e40ca0) API Key authorized because method 'ANY /forms' does not require API Key. Request will not contribute to throttle or quota limits
(b66b3876-984b-11e9-95eb-dd93c7e40ca0) Usage Plan check succeeded for API Key and API Stage 1234567890/Prod
(b66b3876-984b-11e9-95eb-dd93c7e40ca0) Starting execution for request: b66b3876-984b-11e9-95eb-dd93c7e40ca0
(b66b3876-984b-11e9-95eb-dd93c7e40ca0) HTTP Method: GET, Resource Path: /forms
(b66b3876-984b-11e9-95eb-dd93c7e40ca0) Lambda execution failed with status 200 due to customer function error: select count(*) AS `count(*)` from (select `user`.* from `user` where (id IN ('some_id_123'))) as `temp` - Cannot enqueue Query after fatal error.. Lambda request id: 1ae2bb06-5347-4775-9277-caccc42f18f2
(b66b3876-984b-11e9-95eb-dd93c7e40ca0) Method completed with status: 502
(b66b3876-984b-11e9-95eb-dd93c7e40ca0) AWS Integration Endpoint RequestId : 1ae2bb06-5347-4775-9277-caccc42f18f2
(b66b3876-984b-11e9-95eb-dd93c7e40ca0) X-ray Tracing ID : 1-5d13cca0-3be96a1ab93a877edc70577c
Example correlated Lambda execution logs:
START RequestId: 1ae2bb06-5347-4775-9277-caccc42f18f2 Version: $LATEST
2019-06-26T19:50:56.391Z 1ae2bb06-5347-4775-9277-caccc42f18f2 { "extendedRequestId": "b5zpBGS3IAMFvqw=", ... }
2019-06-26T19:50:57.853Z 1ae2bb06-5347-4775-9277-caccc42f18f2 { "errorMessage": "select count(*) AS `count(*)` from (select `user`.* from `user` where (id IN ('some_id_123'))) as `temp` - Cannot enqueue Query after fatal error.", ... }
END RequestId: 1ae2bb06-5347-4775-9277-caccc42f18f2
REPORT RequestId: 1ae2bb06-5347-4775-9277-caccc42f18f2 Duration: 1660.45 ms Billed Duration: 1700 ms Memory Size: 256 MB Max Memory Used: 57 MB
Other Thoughts: Export the Swagger definitions of both the broken API and the working API. Compare and see what is different. Do this from the console by going to Stages > Prod > Export > Export as Swagger + API Gateway Extensions. It may not be exactly the same as the CloudFormation template, but it's pretty close.
At the time of this post, Lambda Proxy Integration (AWS_PROXY) and CORS (Access-Control-Allow-Origin) don't work very well together. My approach -inspired on this explanation- was to use AWS instead of AWS_PROXY and manually provide Mapping templates for both request and response as follows:
MyApiGateway:
Type: AWS::Serverless::Api
Properties:
StageName: !Ref Stage
Cors:
AllowMethods: "'POST,OPTIONS'"
AllowHeaders: "'Access-Control-Allow-Origin,Content-Type,X-Amz-Date,Authorization,X-Api-Key,x-requested-with,x-requested-for'"
AllowOrigin: "'*'"
DefinitionBody:
swagger: 2.0
info:
version: 1.1
title: !Ref AWS::StackName
paths:
/mypath:
get:
responses:
"200":
schema:
$ref: "#/definitions/Empty"
headers:
Access-Control-Allow-Origin:
type: string
x-amazon-apigateway-integration:
httpMethod: POST # must be POST even for GET
type: AWS # must be AWS to allow cors headers
uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyLambda.Arn}/invocations
requestTemplates:
application/json: |
{
#set($params = $input.params().querystring)
"queryStringParameters" : {
#foreach($param in $params.keySet())
"$param" : "$util.escapeJavaScript($params.get($param))" #if($foreach.hasNext),#end
#end
},
#set($params = $input.params().path)
"pathParameters" : {
#foreach($param in $params.keySet())
"$param" : "$util.escapeJavaScript($params.get($param))" #if($foreach.hasNext),#end
#end
}
}
responses:
default:
statusCode: 200
responseParameters:
method.response.header.Access-Control-Allow-Origin: "'*'"
responseTemplates:
application/json: |
#set($payload = $util.parseJson($input.json('$')))
#set($context.responseOverride.status = $payload.statusCode)
$payload.body