How to properly call AWS Lambda Function from API Gateway? - amazon-web-services

I was messing with Lambda recently, and finally got my lambda code running properly. Or at least when I test it using the "Test" from the Lambda page itself, where I can write my JSON by hand.
I need to run this function through API Request, so in my server I was expecting to make a POST request with the JSON data I had in my "Test" before. Turns out it returns me a 502 server error. I`ve tried to test it using the Amazon API Request page, where I can test by choosing the request TYPE, body, queryStrings and so on. And still did not work.
I had a earlier version of this lambda function working with guzzle before. It just required GET parameters, and it was quite simple to setup using guzzle in PHP.
I think this should be very simple and I'm missing something.
Thanks!
info = $guzzle->post('https://my-secret-url.execute-api.us-west-2.amazonaws.com/prod/lambda-function-name', [
'query' =>
[
'out' => 'lambda/piperun.pdf',
'in' => 'invoice,propostas_7_5.pdf'
],
'json' => $this->proposta->getJSONData() //Same JSON from image
]);

Related

503 error when fetching an internal NextJS api with query parameters on AWS Amplify

I am trying to fetch data from a JSON file through NextJS internal API on the client side. But it is always throwing 503 error:
The Lambda function associated with the CloudFront distribution is invalid or doesn't have the required permissions.
We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.
I tried to use the GET method with query params in the URL, but it didn't work, then I try the POST method with the query in the body(just to test out), but it also didn't work either.
Here is the code:
const response = await fetch(`/api/search?q=${query}`, {
method: "GET",
headers: {
'Content-Type': 'application/json',
},
})
const res = await response.json()
I have another component that sends some user inputs to save in my DB, and it is working perfectly. (I am really confused why one works but not other given both are equivalent request)
Also, the same app deployed on Vercel is working perfectly. So I think the issue is with Amplify.
Anyone had similar issues with the Next app on Amplify? please help.
most likely you are sending a GET request but you have something in the body. e.g. form-data. this is example in postman.

Slack slash-command through AWS API Gateway to AWS Lambda (Python versus Java)

I am trying to connect a Slack slash-command to an AWS Lambda (through the AWS API Gateway).
I was able to adapt the Hello, World blueprint (written in Python) in the Lambda tutorial section. I set up an API gateway as a trigger, then had Slack POST the slash-command to the API endpoint. I had to manually decode the base64 body, then use parse_qs to convert the query string-like POST body into a dictionary, where I could then access it just fine.
My real Lambda code is currently in Java, but I've started with the java-basic sample app from the Developers Guide. I built the app, uploaded the jar, and confirmed the correct handler was being called. I set up another API gateway and pointed a different Slack slash-command at the new endpoin. It fails.
The log looks like:
java.lang.RuntimeException: An error occurred during JSON parsing
Caused by: java.io.UncheckedIOException: com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.lang.String` out of START_OBJECT token
at [Source: (ByteArrayInputStream); line: 1, column: 1]
I'm guessing this means Slack is sending the same query string-like argument in the POST body, and for some reason, something is expecting JSON input, not just text. I don't understand why the Python handler was okay with building up an event dictionary and making the Lambda decode the POST body, whereas the Java handler is never getting called, but is dying before that when attempting to deserialize the POST body, thinking it's JSON.
Both Lambdas and API gateways were set up with the usual defaults, AFAICT.
I solved the problem by switching to using the HandlerStream example. I can then get the "body" from the event, Base64.decodeBase64 it, then unpack the form parameters with UriParameterMap.parse.
I then process the incoming text that came from the Slack slash command and then return a string of JSON that Slack expects.

AWS API Gateway returning different status via Postman to Method Test

I have an AWS Lambda integrated into API Gateway. The lambda is current just returning an error:
exports.handler = (event, context, callback) => {
context.fail(JSON.stringify({
status: 500,
errors: 'This is definitely the same endpoint.'
}));
};
I have added an HTTP status 500 response in method response of API Gateway, and I have mapped an integration response using regex *"status":500.* to the 500 response.
When I test this using the Method Test functionality in AWS, I get the 500 response I expect:
But when send command to the endpoint with Postman, I get a 200 status:
How can this be? The Method Test seems to suggest my Integration Response and Method Response setups are correct, and I have my regex set up correctly, but what am I missing between the API Gateway and the rest of the world that would produce this different result?
Have you tried Deploying the API? Maybe a redeployment might fix the issues.
did you stumble across the Handle Custom Lambda Errors in API Gateway guide already?
The format suggested there is:
{
"isBase64Encoded" : "boolean",
"statusCode": "number",
"headers": { ... },
"body": "JSON string"
}
So you basically need to return this JSON structure. I check this with AWS serverless express library (line 100-105) - which we use - and it's returning this structure.
The major challenge is, that sending the HTTP response to the client is a task for the API Gateway and to do so, you must return a valid JSON response from the lambda in a format that the API gateway unterstands. The execution status of the lambda will be also 200 (because it worked A-Okay) but the API Gateway will transform your response into a 500. This is also why you nedd this double/triple JSON encoding (JSON-as-string in JSON-attributes).

AWS API Gateway Lambda function works with Postman but not with jquery

I have a lambda (node) function that works fine when I invoke it using postman but not when I used jquery $.ajax.
The function is being called from a local html page using javascript/jquery.
I have the 'Allow-Control-Allow-Origin' chrome plugin enabled.
The request passes the same json object using possman and jQuery.
{
"deviceid" : "ZZ-5A-04-A6-XX-YY"
}
I tried the following gateway request mapping templates.
$input.json('$')
When I log the even node object I see the following line
deviceid=ZZ-5A-04-A6-XX-YY
$input.body
I get the error:
Could not parse request body into json: Unrecognized token
Solved this finally.
In addition to using the chrome allow cross origin plugin the data object needs to be send as a string when using jquery ajax.
data: JSON.stringify(hardobj)
Hope someone else does not have to waste a week trying to figure this one out.

How to return nothing in AWS API Gateway?

Sorry for this dumb question, but I tried everything.
I have a AWS API Gateway from a Lambda function that I need to return only HTTP Code 200 with no body. If the lambda returns a empty string, the body shows "" (2 quotation marks). If the lambda returns null, the body shows the word null.
What is the catch? How to return a empty body?
For information, I am using a Slack dash command to call the API. So the call returns a HTTP 200 OK, and the result is sent by POST in a response url; so processing can be done after the HTTP result, in order to avoid timeout problems.
If you are using the "lambda proxy integration" in the "integration request" section (see attached screenshot), you can simply return an empty string through the following structure.
module.exports.hello = (event, context, callback) => {
const response = {
statusCode: 200,
body: ''
};
callback(null, response);
};
I experienced exact the same issue. Lambda Proxy Integration didn't work for me. (Lambda didn't received the request from API Gateway. I think the Proxy disabled Integrated Request > Mapping Template, which transforms slack's application/x-www-form-urlencoded into JSON that Lambda can read.)
Instead, I got another resolution: using Integrated Response. Selected 200 and added Mapping Template then fill in the following code:
#set($inputRoot = $input.path('$'))
After saving and deploying the API (Be sure to return null in the Lambda Function), I got the problem solved. (In my case, I wanted to hide the slash command the user typed in and only show the results.)
I've referenced this article: https://medium.com/#farski/learn-aws-api-gateway-with-the-slack-police-ca8d636e9fc0