Unable to access query string params inside AWS Api Gateway - amazon-web-services

I have configured a resource with a GET method on AWS API Gateway. Integration type is configured as HTTP, but it seems that I cannot access Url Query string parameters without Lambda Functions.
For example
I have api endpoint https://api.domain.com/v1/object/500?param_id=305 and I would like to integrate it with an existing http such as http://somedomain.com/object/500?param_id=305
When I define endpoint URL such as http://somedomain.com/object/{id}?param_id={param_id} I am not able to define param_id as url query string parameter
I am getting a following error:
Invalid mapping expression specified: Validation Result: warnings : [], errors : [Invalid mapping expression parameter specified: method.request.querystring.param_id
How can I access query string params without using Lambda functions?

You can use body mapping template in the integration request section and get request body and query strings. Construct a new JSON at body mapping template, which will have data from request body and query string. As we are adding body mapping template your business logic will get the JSON we have constructed at body mapping template.
Inside body mapping template to get query string please do ,
$input.params('querystringkey')
For example inside body mapping template,
#set($inputRoot = $input.path('$'))
{
"firstName" : "$input.path('$.firstName')", //This is to get path variable
"lastName" : "$input.path('$.lastName')"
"language" : "$input.params('$.language')" //This is to get query string
}
Please read https://aws.amazon.com/blogs/compute/tag/mapping-templates/ for more details on body mapping template

Related

API GATEWAY not retreiving request body

I'm trying to create a POST endpoint in API gateway with request body in application/json type. Now, in input body mapping template, I want to check if the input is there and if the required fields are present or not. I tried getting input body using $input.body and also tried $input.json('$') and $input.path('$'). Nothing works, input body is always empty, although the $input.body == "" check always returns false. But in the test logs i can see that the body is passed through. I'm using Mock as integration type. What can be an issue?
I found out the answer to this is that, actually the reponse body isn't accessible when we use MOCK integration as provided by AWS, but we can still access body using a hacky method by:
First, in the integration request mapping template you store the body in a path parameter.
#set($context.requestOverride.path.body = $input.body)
{
"statusCode": 200,
}
Then, in the integration response mapping template you fetch it back and return it.
#set($body = $context.requestOverride.path.body)
{
"statusCode": 200,
"body": $body,
}
And then to parse it:
$util.parseJson($body).varName

How to pass event info from aws API Gateway get to Lambda?

How do I refer to API Gateway GET query string parameters in a Lambda function ?
When I test I can use my local test event with "username": "larry"
When I test with a post I can use the body parameters as the event with "username": "larry"
With a get request, I don't have a body. How could I use query string parameters and then refer to them in the request. What event or other attribute do I use to get at the query param or what setting or change do I need to make?
Method request
Integration request
Query String
When testing I've referred to event["username", what do I do for an API request passing it as a query string parameter?
Login and click to API gateway and click on method - GET method
Go to Method Execution - select URL Query String Parameter and add query String parameter username
Now go to Integration Request tab Choose Body Mapping Template,
"content type application/json"
Generate Template like below
{
"username": "$input.params('username')"
}
Now write ;ambda which accept key value in pair .
module.exports.get = (event, context, callback) => {
const { username } = event.pathParameters;
console.log("username", username);
}
Now go and deploy your api on apigetway and find url and hit in browser example
https://xxx.yyy-api.us-east-2.amazonaws.com/prod/username?vaquarkhan
Hope it will help
https://docs.aws.amazon.com/de_de/apigateway/latest/developerguide/welcome.html
https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html#api-gateway-set-up-lambda-proxy-integration-on-proxy-resource

How do I map path parameters from an API Gateway API to the Request Object of a Java Lambda

I have a lambda, written in Java, that accepts a Request Object of the structure
{
"id": "be1c320a-144f-464d-b32c-38ec7fb4445b",
"userId": "foobar"
}
When I call this Lambda through the test interface with such an object, it works fine.
I want to create an API where a GET request to
/users/foobar/items/be1c320a-144f-464d-b32c-38ec7fb4445b
i.e. of the form
/users/{userId}/items/{id}
calls this Lambda.
I have created the API resources /users, {userId}, items, and {id} appropriately.
And I have created the GET method (on /users/{userId}/items/{id})and associated it to the lambda.
When I test the API, it invokes the lambda, but with null values in the request. I can see it package the path as {"id":"be1c320a-144f-464d-b32c-38ec7fb4445b","userId": "foobar"} in the logs, but that's not being sent in the body.
I have tried creating a template map (and have tried RTFM), but cannot see how to map path parameters to a body.
How do I achieve this mapping?
I think your Request Object structure may not be properly configured. There may be a few ways to configure this. Here is some information that has helped me.
How to pass a querystring or route parameter to AWS Lambda from Amazon API Gateway - Demonstrates this mapping (albeit with python). However, taking the top response, if you enable "Use Lambda Proxy integration", you can similarily do this with Java as so:
#Override
public Object handleRequest(APIGatewayProxyRequestEvent input, Context context) {
Map<String, String> pathParameters = input.getPathParameters();
String id = pathParameters.get("id");
String userId = pathParameters.get("userId");
// Handle rest of request..
}
This is a tuturial using the serverless framework to create an Api with Java. This tutorial similarily accesses the pathParameters by parsing the input rather than using the APIGatewayProxyRequestEvent java class.
#Override
public Object handleRequest(Map<String, Object> input, Context context) {
try {
// get the 'pathParameters' from input
Map<String,String> pathParameters = (Map<String,String>)input.get("pathParameters");
String id = pathParameters.get("id");
String userId = pathParameters.get("userId");
} catch (Exception ex) {
logger.error("Error in retrieving product: " + ex);
}
}
Use a mapping template.
First, in the Method Request section, you should see userId and id as Request Paths
Then, in the Integration Request, do not choose Proxy Integration.
Then in the Mapping Templates section, add a new mapping template for application/json of the form
{
"id" : "$method.request.path.id",
"userId" : "$method.request.path.user_id"
}

Finding the request's URL in a Lambda function

I have a Lambda function which is called through an API Gateway using a URL. I need to return a variation of the request's URL by which the Lambda function was originally called in the response. How can I find the URL of the request in a Lambda function?
I was hoping I can pass the URL as a parameter to the Lambda function using API Gateway's mapping template. But I don't see how I can do so!
This body mapping template should give you all you need:
{
"host" : "$input.params('Host')",
"path" : "$context.path"
}
So, for where the url called was 'xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/stage/resource', this will pass an event into Lambda that looks like this:
{
host: 'xxxxxxxxxx.execute-api.us-east-1.amazonaws.com',
path: '/stage/resource'
}
If you are using the Use Lambda Proxy integration you can piece it together from the event properties. This is how I did it in python:
host = event["headers"]["Host"]
path = event["requestContext"]["path"]
proto = event["headers"]["X-Forwarded-Proto"]
request_url = f"{proto}://{host}{path}"

How do I define URL query parameters in my Body Mapping Template in AWS API Gateway?

My api is of the form:
https://<>.execute-api.us-east-1.amazonaws.com/Testing/api/v1/mobs/<>.json?filename=<>.json&assertion=1
Currently, I have just defined till the .../mobs/<>.json in my Mapping Template, like this:
{
"mob_type": "$input.params('type')"
}
Now, I added query parameters to the url, which are filename and assertion. So, how do I define them in the Body Mapping Template?
This, doesn't work:
{
"mob_type": "$input.params('type')"
"filename": "$input.params('filename')"
"assertion": "$input.params('assertion')"
}
In the Integration Request under "URL Query String Parameters", you need to add a mapping for
method.request.querystring.type
method.request.querystring.filename
method.request.querystring.assertion
http://docs.aws.amazon.com/apigateway/latest/developerguide/request-response-data-mappings.html#mapping-request-parameters
With the mapping, they are accessible in the Body Mapping Templates.