Why i am getting this {"message": "Internal server error" } from Postman - amazon-web-services

I am new to AWS, I am getting {"message": "Internal server error"} while running the Lambda function with API Gateway in Postman.
I have checked the CloudWatchLogs, there is no error showing in the logs. But Postman returning {"message": "Internal server error"} this error.

It happens when you don't return the correct API Gateway format.
Try to return this in your Lambda:
def lambda_handler(event, context):
return {
"statusCode": 200,
"body": "{'Test': 'Test'}",
"headers": {
'Content-Type': 'text/html',
}
}

According to the log message you provide, it looks like the log from your Lambda function. I recommend you to enable logging feature on API Gateway side or you can use the test invoke feature on API Gateway console. They both are able to help you to debug your API.
Here is the common issues which might be able to help you diagnose the issue.
1. It doesn't have a right permission to allow API Gateway invoke your Lambda function.
2. It is set as AWS Service Proxy to your Lambda function, the response from your Lambda function doesn't return the response in the proper format.
Ref: https://forums.aws.amazon.com/thread.jspa?messageID=916452

The error can be caused by incorrect quotation marks.
A. Examples that produce the same error in Postman tests:
1. def lambda_handler(event, context):
return {
'statusCode': 200,
"body": {"one": 1000}
}
2. def lambda_handler(event, context):
return {
'statusCode': 200,
"body": "{"one": 1000}"
}
B. Examples that do not produce the error:
3. def lambda_handler(event, context):
return {
'statusCode': 200,
"body": "{'one': 1000}"
}
4. def lambda_handler(event, context):
return {
'statusCode': 200,
"body": '{"one": 1000}'
}
So, the type of quotation marks used after "body": is the reason for the error in this case. Note that while the Amazon lambda console does not produce an error for example 1., Postman says { "message": "Internal server error" }

Resolved it by adding isBase64EncodedFlag to my lambda response
results = {
"statusCode": 200,
"headers": {"Content-Type": "application/json"},
"body": json.dumps(res),
"isBase64Encoded": False
}

Related

AWS API gateways CORS error when reading from post body

I have an application written in React JS, running on localhost, which makes API calls to API Gateway in AWS. API Gateway forwards requests to a lambda function, which returns a response. I have enabled CORS on AWS side.
At the moment whenever I click a 'request' button in the application I get a response from the gateway. Here is my current python code:
import json
def lambda_handler(event, context):
response = {}
response['result'] = "Success"
response['message'] = "Updated successfully!"
return {
'headers': {
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST'
},
"body": json.dumps(response)
}
And here's the body of the request:
{
"ID": "1101",
"RequestDate": "2021-02-28"
}
This works fine. I get the 'message' value from this response and can display it without problems.
Next I want to display the information containing some data coming from the request. For example instead of Updated successfully I would like to get the RequestDate from the request and return Updated successfully on 2021-02-28.
I added these two lines:
def lambda_handler(event, context):
body = json.loads(event['body'])
request_date = body['RequestDate']
response = {}
response['result'] = "Success"
response['message'] = "Updated successfully!"
return {
'headers': {
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST'
},
"body": json.dumps(response)
}
As soon as I make this change I get the following code in my application:
Access to fetch at url from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
This only happens when I add request_date = body['RequestDate']. I tried returning the body only and it was working fine as well.
In my react js application I add following headers as well:
async callAPI(url, method, data) {
let result = await fetch(url, {
method: method,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify({
data
})
})
return result.json().then(body => this.notify(body['message']));
}
I tried enabling CORS and deploying the resource again but to no avail. I have added Access-Control-Allow-Origin to allowed headers in AWS. As I mentioned it works fine with post method prior to adding that one line. What could be wrong here and how can I remedy it?
EDIT:
One more thing. I get this error only from my application running on localhost. Curling or using any REST client works fine.
EDIT2:
Added fetch code
Setting up CORS in Lambda is dependent on how you setup API Gateway. API Gateway has several modes [REST, HTTP, WebSocket]. In the case of REST, API Gateway does some pre-processing on the incoming request like parameter validation before passing to Lambda. HTTP Proxy is just that, a pass through to Lambda, and Websockets is not really for this discussion.
I am assuming it is because you are using API Gateway in standard configuration and you have not enabled CORS on API Gateway. The code you provided above will work for API Gateway Configured for HTTP.
If you are using the CDK, or CloudFormation then you must configure CORS there, else the easiest is to use the console.
Go to your API in the AWS Console, select resources, select your method or service, from the actions menu enable CORS. And then publish your updated API.
Here is a link to the AWS documentation that outlines how to do it.
Some advice, when testing endpoints via a browser it is best not to use Localhost or 127.0.0.1 it has unintended consequences. Edit your hosts file and give yourself a domain name, and use that domain name instead.
CORS is there for a reason to prevent Cross Site Scripting or Cross Site Origin Attacks. Try not to use *, testing sure, but production no. If you have code say on S3, and your REST services on say API Gateway you can front both with CloudFront using the same Origin, and let CloudFront know to forward based on URL (e.g /API) to APIGateway and the other to S3. Thus everything has the same domain.
This is what I have on my server and it works fine. Using fetch on the front-end.
Server Code:
import json
result = {"hello": "world"}
return {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json',
"Access-Control-Allow-Origin": "*"
},
'body': json.dumps(result)
}
Front-end Code using ES6
url = "Your url"
path = "Your desired path"
data = {"hello": "world"}
const response = await fetch(url + path, {
method: "POST",
cache: "no-cache",
mode: "cors",
body: JSON.stringify(data),
});
Add statusCode inside response from lambda
return {
'statusCode': 200,
'headers': {
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST'
},
'body': json.dumps(response)
}
In case there is any error in your lambda it will return default 5XX response without any CORS headers and in such cases browser will complain for cors headers not found.
You can add your current code in try block and in except block you can print the error and return some default response like below
return {
'statusCode': 500,
'headers': {
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST'
},
'body': json.dumps({'message':'Unexpected error'})
}
Add some log statements in your lambda and check api gateway configuration for Lambda proxy setting.
Make sure you check your api gateway logs and lambda function logs for some more details regarding error.

Internal server error AWS API Gateway with custom authorizer

I am trying to protect a lambda function using a custom authorizer (which validates a jwt) on AWS API Gateway. I also want to pass any queryStringParameters into my lambda function, so I want to keep my Integration request to be Lambda Proxy.
The custom authorizer is set, tested and working
Problem:
When I call this endpoint (after deploying), I receive a HTTP 500 response.
{
"message": "Internal server error"
}
When I remove my custom authorizer OR deselect the lambda Proxy integration, I receive a normal output from my lambda
def lambda_handler(event, context):
return {
'status': 400,
'body' : json.dumps('hello World'),
'headers': {
'Access-Control-Allow-Origin': "*"
},
'isBase64Encoded': 'false'
}
Has anyone come across this? AWS documentation on this issue is sparse :/
Thank you!
I'm hitting myself in the head after this. The reason is because of what my lambda function was returning. It should've been
def lambda_handler(event, context):
return {
'statusCode': 400,
...
As opposed to
def lambda_handler(event, context):
return {
'status': 400,
...
If the AWS docs were better/i wasn't as obtuse :D

AWS Lambda returns respond as 502 Bad request for option method

I have a lambda (LAMBDA_PROXY) function with API gateway which is implemented in Golang (go-chi router).
when I invoke lambda from postman or browser, it gives 502 Bad Gateway status. In CloudWatch, I found following error message
Error while generating proxy response: Status code not set on response: errorString null
You need to respond with the correct response when using the "Use Lambda as Proxy" checkbox. Check out this document.
This may be more appropriate
The error you are getting is because, when you're using the API Gateway + Lambda proxy integration, the return value from the lambda function must be in the following JSON format:
{
"isBase64Encoded": true|false,
"statusCode": httpStatusCode,
"headers": { "headerName": "headerValue", ... },
"body": "..."
}
Since you are using Golang, you can edit the return value of your main.go function by adding the following snippet as follows :
return events.APIGatewayProxyResponse{
Body: string(body),
StatusCode: 200
}, nil
Hope this helps!

Amazon Lambda function return wrong response

I'm using AWS S3, API Gateway and Lambda function to resize my images on the fly. I keep having this error when the image doesn't exist:
Failed to load resource: the server responded with a status of 502 ()
It should return a 404 instead. Here the code in the lambda function:
S3.headObject({Bucket: BUCKET, Key: parameters.orignalImagePath}, function(err,data) {
if(err) {
console.log("[404] Image Not Found: " + parameters.orignalImagePath);
return callback(null, {
statusCode: '404',
body: '{ "message":"Image not found." }',
})
}
});
Here the logs from CloudWatch:
START
{"errorMessage":"The specified key does not exist.","errorType":"NoSuchKey"....}
[404] Image Not Found: Folder/image.png
END
Why i'm getting a 502 when my code return a 404. I checked the ApiGateway settings but couldn't find anything.
I found this: https://aws.amazon.com/premiumsupport/knowledge-center/malformed-502-api-gateway/
It might be because of the malformed response. I'm going to try with the updated response and the four fields.
{
"isBase64Encoded": true|false,
"statusCode": httpStatusCode,
"headers": { "headerName": "headerValue", ... },
"body": "..."
}
UPDATE: It definitely helps to change the response with those 4 fields. However, the same request gets sometimes a 404 and sometimes a 502.

aws apigateway lambda always return 502

I have created aws apigateway lambda integration for my proxy server. When i am making get request to the gateway, the request is successfully going through. The lambda function also executes successfully and writes response in outputstream with statusCode as 200. But apigateway always returns 502.
Snippet of handleRequest():
BufferedReader reader = new BufferedReader(new
InputStreamReader(inputStream));
JSONObject event = (JSONObject) parser.parse(reader);
request = Input.builder().setEvent(event).build();
Response response = requestManager.handleRequest(request);
logger.log(String.format("Response [%s]", response.toString()));
JSONObject responseJson = new JSONObject();
responseJson.put("statusCode", response.getStatusCode());
responseJson.put("headers", response.getHeaders());
JSONObject jsonBody = (JSONObject) parser.parse(response.getBody());
responseJson.put("body", jsonBody);
OutputStreamWriter writer = new OutputStreamWriter(outputStream, "UTF-8");
logger.log("response recieved");
logger.log(String.format("responseJson [%s]", responseJson));
writer.write(responseJson.toJSONString());
writer.close();
logger.log(String.format("output stream [%s]", outputStream));
Am i missing anything ?
502 errors with Lambda usuaully indicate that you are using the Lambda proxy method and not generating the proper JSON response. Make sure your response adheres to the appropriate format.
If you are still having problems, please share a sample JSON generated by your Lambda function.
I had the same issue where all of my logs were saying the lambda executed successfully but API Gateway was still returning 502s on every request. Turns out I forgot to configure the response status codes in the API Gateway Console so it was throwing errors because the response was "incorrect" even with proper formatting. Just add in a status code 200, 400, 403, etc. to the route on your gateway and that might solve your problem.
Make sure you're hitting your callback with the response before calling context.succeed(event) or some other call to context.
This was my problem and putting my callback first fixed the persistent 502 res.
There are two versions of the response format. It might be that are posting a version 1 format response to an endpoint expecting version 2:
Lambda function response for format 1.0
With the 1.0 format version, Lambda integrations must return a response in the following format.
{
"isBase64Encoded": true|false,
"statusCode": httpStatusCode,
"headers": { "headername": "headervalue", ... },
"multiValueHeaders": { "headername": ["headervalue", "headervalue2", ...], ... },
"body": "..."
}
Lambda function response for format 2.0
With the 2.0 format version, API Gateway can infer the response format for you. API Gateway makes the following assumptions if your Lambda function returns valid JSON and doesn't return a statusCode:
isBase64Encoded is false.
statusCode is 200.
content-type is application/json.
body is the function's response.
The following examples show the output of a Lambda function and API Gateway's interpretation.
Lambda function output
API Gateway interpretation
"Hello from Lambda!"
{ "isBase64Encoded": false, "statusCode": 200, "body": "Hello from Lambda!", "headers": { "content-type": "application/json" }}
{ "message": "Hello from Lambda!" }
{ "isBase64Encoded": false, "statusCode": 200, "body": "{ \"message\": \"Hello from Lambda!\" }", "headers": { "content-type": "application/json" }}
To customize the response, your Lambda function should return a response with the following format:
{
"cookies" : ["cookie1", "cookie2"],
"isBase64Encoded": true|false,
"statusCode": httpStatusCode,
"headers": { "headername": "headervalue", ... },
"body": "Hello from Lambda!"
}