I have built a custom authorizer for AWS in .net core. When testing it from API Gateway Console I am receiving ResponseCode 500 with this error.
Execution log for request 0566bf99-cfb5-11e8-b203-65db1a667292
Sun Oct 14 13:28:22 UTC 2018 : Starting authorizer: i07xnl for request: 0566bf99-cfb5-11e8-b203-65db1a667292
Sun Oct 14 13:28:22 UTC 2018 : Incoming identity: **ds
Sun Oct 14 13:28:22 UTC 2018 : Endpoint request URI: https://lambda.us-west-2.amazonaws.com/2015-03-31/functions/arn:aws:lambda:us-west-2:278483347755:function:GetPolicy/invocations
Sun Oct 14 13:28:22 UTC 2018 : Endpoint request headers: {x-amzn-lambda-integration-tag=0566bf99-cfb5-11e8-b203-65db1a667292, Authorization=************************************************************************************************************************************************************************************************************************************************************************************************************************4e3e8c, X-Amz-Date=20181014T132822Z, x-amzn-apigateway-api-id=k8ate5przg, X-Amz-Source-Arn=arn:aws:execute-api:us-west-2:278483347755:k8ate5przg/authorizers/i07xnl, Accept=application/json, User-Agent=AmazonAPIGateway_k8ate5przg, X-Amz-Security-Token=FQoGZXIvYXdzEA0aDBDj/T/Y58E+lkgRcyK3A5EXzDygzB0DzIFN36D/LMM0uCMn70NDKnpualhTEKEe8Zj/a6/nSFVwDSmQty8r2b/ezWcJoQCQztPHDiTFFu7I/4vvoGuH6P3REduQn8knZGVkBAOFTi/EIcnLNBoWjWQXrO8BszGKdoykJ3BrTIq+2dbyfOUdIcmCwGGyC/UzGn5B+fkNcSJT94yfemVcfEiuncnx6snRekDYzRZWXW1+ZzxPoMINpykNTYbKCnG5pNzPF7j2xxH7zyfYtmsVaMaq5zBGqT3eGzUonM4k/7FIRwOB6SxRUIHrO/fboa3QW+z7+iQEtqWg7DDO [TRUNCATED]
Sun Oct 14 13:28:22 UTC 2018 : Endpoint request body after transformations: {"type":"TOKEN","methodArn":"arn:aws:execute-api:us-west-2:278483347755:k8ate5przg/ESTestInvoke-stage/GET/","authorizationToken":"sdds"}
Sun Oct 14 13:28:22 UTC 2018 : Sending request to https://lambda.us-west-2.amazonaws.com/2015-03-31/functions/arn:aws:lambda:us-west-2:278483347755:function:GetPolicy/invocations
Sun Oct 14 13:28:24 UTC 2018 : Authorizer result body before parsing: {"Version":"10/14/18","Statement":[{"Effect":"Allow","Action":["apigateway: POST"],"Resource":["arn:aws:lambda:us-west-2:278483347755:function:GetPolicy"]}]}
Sun Oct 14 13:28:24 UTC 2018 : Execution failed due to configuration error: Invalid JSON in response: {"Version":"10/14/18","Statement":[{"Effect":"Allow","Action":["apigateway: POST"],"Resource":["arn:aws:lambda:us-west-2:278483347755:function:GetPolicy"]}]}
Sun Oct 14 13:28:24 UTC 2018 : AuthorizerConfigurationException
The Invalid Json is this:
{
"Version": "10/14/18",
"Statement": [{
"Effect": "Allow",
"Action": ["apigateway: POST"],
"Resource": ["arn:aws:lambda:us-west-2:278483347755:function:GetPolicy"]
}]
}
To me this seems Okay. Here, Action value is taken from AWS documentation and Resource is the ARN for my custom authorizer lambda method.
The response isn't correct for a custom authorisation lambda.
You can see the full details here (https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-lambda-authorizer-output.html), however for your example you need to return:
{
"principalId": "user",
"policyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Allow",
"Resource": "arn:aws:execute-api:us-west-2:278483347755:k8ate5przg/ESTestInvoke-stage/GET/"
}
]
}
}
Specifically you need to nest your policy in a policyDocument key, and the permission you're granting is not to be able to POST to API Gateway, but to be allowed to invoke the function behind the gateway.
Related
I am trying to create a serverless contact form in S3 that calls AWS API Gateway that then interacts with SES to send an email to a "contact us" email recipient. I am following the tutorial at https://levelup.gitconnected.com/creating-a-serverless-contact-form-on-aws-ff339ad1fa60 and am stuck at the part where I've created the API and am trying to test it with a JSON payload. The problem is the API test behaves as expected and returns a successful http 200 BUT it seems SES is returning an error that looks like ->
{"Error":{"Code":"SignatureDoesNotMatch","Message":"The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.","Type":"Sender"},"RequestId":"1559f1b5-7000-4fe5-9d70-38b729adba46"}
Here is the entire execution stack from the API test in the AWS API configuration area ->
Execution log for request a18a0aa1-fa42-4bc8-a3c0-c6754716398f
Fri Dec 02 20:19:12 UTC 2022 : Starting execution for request: a18a0aa1-fa42-4bc8-a3c0-c6754716398f
Fri Dec 02 20:19:12 UTC 2022 : HTTP Method: POST, Resource Path: /
Fri Dec 02 20:19:12 UTC 2022 : Method request path: {}
Fri Dec 02 20:19:12 UTC 2022 : Method request query string: {}
Fri Dec 02 20:19:12 UTC 2022 : Method request headers: {}
Fri Dec 02 20:19:12 UTC 2022 : Method request body before transformations: {
"name": "Test Name",
"email": "test#test.com",
"phone": "123-456-7890",
"message": "This is a test message!"
}
Fri Dec 02 20:19:12 UTC 2022 : Endpoint request URI: https://email.us-east-1.amazonaws.com/SendEmail
Fri Dec 02 20:19:12 UTC 2022 : Endpoint request headers: {Authorization=************************************************************************************************************************************************************************************************************************************************************************098c83, X-Amz-Date=20221202T201912Z, x-amzn-apigateway-api-id=1j6iefoiqj, Accept=application/json, User-Agent=AmazonAPIGateway_1j6iefoiqj, X-Amz-Security-Token=IQoJb3JpZ2luX2VjEJX//////////wEaCXVzLWVhc3QtMSJHMEUCIAVdXRcxBZlgf9mN9jqp6OxEtITF/KMl+MzbXyb89NZrAiEAzSxr6P0cIMDwGDkkXOYr1C2KINbRKN2X0zozBMh7fjIq7gIIrf//////////ARADGgwzMzc2MzIxMzUyNDQiDHpwxD6RfZw5uGjCHirCAse0l62z8auypaCu5K+bUgeCqsXqtE7bjBhct1ZG0WK5q5gw3DRKGLPmqPc9nFZ1pbeRUCw5LvuuI+6jQKs2CCJisZlgrGjSD/m1akgPkVsR1FtCNj6z7GEURaTg6r3aqz2KXyrHVft4cex+BoSOeMUMBBXWOKJirppkK8KGz4yNNPYFJ1BPLWQJcWOb6rPi/87pPoey0E3PiwLf1SXTVzkc/S/I/tpLzV7fARx4vheXC7c+SmAHyg/Zm318As5OBCqGBPXKpK0UT/7z4r9/vqDRzCsXXe0FCGJjOyMuM5y9k5bnsT5sRjpenX1DOkUopLoEsc2xTjunfEXKGmfn+M96I+Z3JbrnGMz [TRUNCATED]
Fri Dec 02 20:19:12 UTC 2022 : Endpoint request body after transformations: Action=SendEmail&Message.Body.Text.Data=%0AName%3A+%22Test+Name%22%0AEmail%3A+%22test%40test.com%22%0APhone%3A+%22123-456-7890%22%0AMessage%3A+%22This+is+a+test+message%21%22&Message.Subject.Data=Contact+form+submission&Destination.ToAddresses.member.1=DudeDudely%40hotmail.com&Source=no_reply_contact_form_submission%40ThatBigTLD.com
Fri Dec 02 20:19:12 UTC 2022 : Sending request to https://email.us-east-1.amazonaws.com/SendEmailToWhomeverILike
Fri Dec 02 20:19:12 UTC 2022 : Received response. Status: 403, Integration latency: 21 ms
Fri Dec 02 20:19:12 UTC 2022 : Endpoint response headers: {Date=Fri, 02 Dec 2022 20:19:12 GMT, Content-Type=application/json, Content-Length=300, Connection=keep-alive, x-amzn-RequestId=1559f1b5-7000-4fe5-9d70-38b729adba46}
Fri Dec 02 20:19:12 UTC 2022 : Endpoint response body before transformations: {"Error":{"Code":"SignatureDoesNotMatch","Message":"The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.","Type":"Sender"},"RequestId":"1559f1b5-7000-4fe5-9d70-38b729adba46"}
Fri Dec 02 20:19:12 UTC 2022 : Method response body after transformations: {"Error":{"Code":"SignatureDoesNotMatch","Message":"The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.","Type":"Sender"},"RequestId":"1559f1b5-7000-4fe5-9d70-38b729adba46"}
Fri Dec 02 20:19:12 UTC 2022 : Method response headers: {X-Amzn-Trace-Id=Root=1-638a5dc0-85f935e6291eab49e7dbe023, Content-Type=application/json}
Fri Dec 02 20:19:12 UTC 2022 : Successfully completed execution
Fri Dec 02 20:19:12 UTC 2022 : Method completed with status: 200
I have also tested this in Postman and I get the same results. The JSON payload I used in the test looks like ->
{
"name": "Test Name",
"email": "test#test.com",
"phone": "123-456-7890",
"message": "This is a test message!"
}
I have an IAM role associated with this api that looks like ```
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Custom",
"Effect": "Allow",
"Action": [
"ses:SendEmail"
],
"Resource": "*"
}
]
}
This IAM role's ARN is referenced in the Integration Request section as
Execution role
arn:aws:iam::<ABigNumberImNotGoingToShowYou>:role/ApiGatewaySes
My main question is ....... do I also need to send some other type of authentication token? If so where would I configure that information?
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
I'm using API Gateway's AWS Service integration type to add logs to the Cloudwatch Logs service using the PutLogEvents action, as described here: https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutLogEvents.html
I've successfully setup a similar type of method to add items into a DynamoDB table using the PutItem action and that worked just fine, so I'm not sure what I'm missing with this one.
I've double checked for typos and problems with my template. Have successfully used PutLogEvents using the CLI tools, so the setup seems all OK.
Here's some screenshots of my setup from the AWS dash:
Here's the mapping template I'm using:
{
"logGroupName": "FromAPI",
"logStreamName": "$input.path('$.streamName')",
"logEvents": [
{
"timestamp": $input.path('$.ts'),
"message": "$input.path('$.message')"
}
]
}
The response I get back has a 200 status code, but the following response body:
{
"Output": {
"__type": "com.amazon.coral.service#UnknownOperationException",
"message": null
},
"Version": "1.0"
}
Here's a redacted (xxx) execution log:
Execution log for request xxx
Fri Apr 19 02:28:58 UTC 2019 : Starting execution for request: xxx
Fri Apr 19 02:28:58 UTC 2019 : HTTP Method: POST, Resource Path: /log
Fri Apr 19 02:28:58 UTC 2019 : Method request path: {}
Fri Apr 19 02:28:58 UTC 2019 : Method request query string: {}
Fri Apr 19 02:28:58 UTC 2019 : Method request headers: {}
Fri Apr 19 02:28:58 UTC 2019 : Method request body before transformations: {
"streamName": "12345",
"ts": 1555641510000,
"message": "help!"
}
Fri Apr 19 02:28:58 UTC 2019 : Endpoint request URI: https://logs.xxx.amazonaws.com/?Action=PutLogEvents
Fri Apr 19 02:28:58 UTC 2019 : Endpoint request headers: {Authorization=xxx, X-Amz-Date=20190419T022858Z, x-amzn-apigateway-api-id=xxx, Accept=application/json, User-Agent=AmazonAPIGateway_xxx, X-Amz-Security-Token=xxx [TRUNCATED]
Fri Apr 19 02:28:58 UTC 2019 : Endpoint request body after transformations: {
"logGroupName": "FromAPI",
"logStreamName": "12345",
"logEvents": [
{
"timestamp": 1555641510000,
"message": "help!"
}
]
}
Fri Apr 19 02:28:58 UTC 2019 : Sending request to https://logs.xxx.amazonaws.com/?Action=PutLogEvents
Fri Apr 19 02:28:58 UTC 2019 : Received response. Status: 200, Integration latency: 38 ms
Fri Apr 19 02:28:58 UTC 2019 : Endpoint response headers: {x-amzn-RequestId=xxx, Content-Type=application/json, Content-Length=105, Date=Fri, 19 Apr 2019 02:28:58 GMT}
Fri Apr 19 02:28:58 UTC 2019 : Endpoint response body before transformations: {"Output":{"__type":"com.amazon.coral.service#UnknownOperationException","message":null},"Version":"1.0"}
Fri Apr 19 02:28:58 UTC 2019 : Method response body after transformations: {"Output":{"__type":"com.amazon.coral.service#UnknownOperationException","message":null},"Version":"1.0"}
Fri Apr 19 02:28:58 UTC 2019 : Method response headers: {X-Amzn-Trace-Id=Root=xxx, Content-Type=application/json}
Fri Apr 19 02:28:58 UTC 2019 : Successfully completed execution
Fri Apr 19 02:28:58 UTC 2019 : Method completed with status: 200
Nothing gets logged into my Cloudwatch Logs stream - the API Gateway integration request response body contains an UnknownOperationException error.
My best guess is that this request is not mapping to the PutLogEvents action for some reason. Strange that the status code is 200 in this situation.
I'm guessing it's just some typo - or an additional header that I need to send through? Any ideas?
It should work if you add the following lines at the top of your Mapping Template:
#set($context.requestOverride.header['X-Amz-Target'] = "Logs_20140328.PutLogEvents")
#set($context.requestOverride.header['Content-Type'] = "application/x-amz-json-1.1")
This is very tricky and not well documented. You can find those headers in the sample request for PutLogEvents.
i need help with Response Body Template.
I am Using POST to "PutItem" in dynamoDB using APIGateway directly(No lambda).
The new item is added successfully but the response is Empty at 200
What I need is
1 - New row data
2 - Status
3 - Message
{
"data": [],
"status": "Success",
"message": "Updated Succesfully"
}
without using lambda...Is this possible?
I tried many stuffs i.e.
#set($inputRoot = $input.path('$'))
{"templateId": "$elem.templateId.S",
"templateFileName": "$elem.templateFileName.S"}
but its showing null.
Here is my log when i run Test #API Gateway
Sat Feb 17 06:22:18 UTC 2018 : Endpoint request body after transformations:
{
"TableName": "xyz-mobilehub-9260364_Template_Table",
"Item": {
"templateId": {
"S": "APIGateway"
},
"templateFileName": {
"S": "breaking-news-story-01-18-2016"
},
"templateName": {
"S": "Just Saying Thank You"
},
"templateType": {
"S": "I really enjoyed this story!!"
}
}
}
Sat Feb 17 06:22:18 UTC 2018 : Sending request to https://dynamodb.us-east-1.amazonaws.com/?Action=PutItem
Sat Feb 17 06:22:18 UTC 2018 : Received response. Integration latency: 33 ms
Sat Feb 17 06:22:18 UTC 2018 : Endpoint response body before transformations: {}
Sat Feb 17 06:22:18 UTC 2018 : Endpoint response headers: {Server=Server, Connection=keep-alive, x-amzn-RequestId=RE631UNS84TACTMP4TE752UK0BVV4KQNSO5AEMVJF66Q9ASUAAJG, x-amz-crc32=2745614147, Content-Length=2, Date=Sat, 17 Feb 2018 06:22:17 GMT, Content-Type=application/x-amz-json-1.0}
Sat Feb 17 06:22:18 UTC 2018 : Method response body after transformations:
{
"templateId": "",
"templateFileName": "",
}
Sat Feb 17 06:22:18 UTC 2018 : Method response headers: {X-Amzn-Trace-Id=Root=1-5a87ca19-62a291f9a923480f5c62884f, Content-Type=application/json}
Sat Feb 17 06:22:18 UTC 2018 : Successfully completed execution
Sat Feb 17 06:22:18 UTC 2018 : Method completed with status: 200
Go to Integration Response in you API Gateway and give the response in the way you want. Please see below screenshots,
Select Integration Response,
under Generate Template provide your JSON data
I have configured my AWS APIGateway to validate the requests according to a JSON schema.
E.g. the path /vehicle, which has the following schema attached:
{
"type":"object",
"properties":{
"licensePlate":{
"pattern":"[A-Za-z]{1,3} [A-Za-z]{1,2} \\d{1,4}",
"type":"string"
},
"vehicleType":{
"type":"string",
"enum":[
"Truck",
"Trailer"
]
}
},
"required":[
"licensePlate",
"vehicleType"
]
}
This works fine. If I submit an invalid request the API responds with a 400 {"message": "Invalid request body"}. I would like to customize this message, e.g. to
{
"entity": "vehicleType",
"message": "missing"
}
If I take a look at the logs from the Gateway it seems that a similar message is logged (object has missing required properties (["vehicleType"])). Can I use that one? How can I access it?
Logs:
Execution log for request test-request
Thu Feb 01 13:12:18 UTC 2018 : Starting execution for request: test-invoke-request
Thu Feb 01 13:12:18 UTC 2018 : HTTP Method: POST, Resource Path: /vehicle
Thu Feb 01 13:12:18 UTC 2018 : Method request path: {}
Thu Feb 01 13:12:18 UTC 2018 : Method request query string: {}
Thu Feb 01 13:12:18 UTC 2018 : Method request headers: {}
Thu Feb 01 13:12:18 UTC 2018 : Method request body before transformations: {
"licensePlate": "HH AB 123"
}
Thu Feb 01 13:12:18 UTC 2018 : Request body does not match model schema for content type application/json: [object has missing required properties (["vehicleType"])]
Thu Feb 01 13:12:18 UTC 2018 : Method completed with status: 400
Is this possible with the API Gateway?
Yeah what you want is the $context.error.validationErrorString
Like #Bajwa said -- you need to customize the GatewayReponse template. If you're using cloud formation that looks like this:
"GatewayResponse": {
"Type": "AWS::ApiGateway::GatewayResponse",
"Properties": {
"ResponseParameters": {
"gatewayresponse.header.Access-Control-Allow-Origin": "'*'",
"gatewayresponse.header.Access-Control-Allow-Headers": "'*'"
},
"ResponseTemplates": {
"application/json": "{\"error\":{\"message\":\"$context.error.messageString\",\"errors\":\"$context.error.validationErrorString\"}"
},
"ResponseType": "BAD_REQUEST_BODY",
"RestApiId": {
"Ref": "YouRestApiResource"
},
"StatusCode": "400"
}
}
If you violate the request body validator you'll see something like this:
{
"error": {
"message":" "Invalid request body"",
"errors":"[string \"1\" is too short (length: 1, required minimum: 10)]"
}
It's not perfect -- some of the messaging is vague, would be nice if anyone knows how to for example add the property name that caused the violation.
If the request payload is invalid, you will see the same message:
{
"message": "Invalid request body"
}
API Gateway includes more detail, if the request payload format is valid and parameters format is invalid.
See more detail from below link, especially the bottom part.
Test Basic Request Validation in API Gateway
But you may do some customization in the response message by customizing Gateway responses.
You may customize Bad Request Body 400.
{
"message":"$context.error.messageString",
"Hint":"Check required number of parameters or parameters allowed type and length."
}
Then you will see message in below format.
{
"message": "Invalid request body",
"Hint": "Check required number of parameters or parameters allowed type and length."
}
See hot to update Body Mapping Template from attached screenshot. (APIGateway/Gateway Responses).