How to get API gateway url in AWS lambda function? - amazon-web-services

I have a scenario where I am using an API URL to invoke lambda function. After invoking the lambda function, I want that particular URL in the lambda function.
https://******.execute-api.eu-west-1.amazonaws.com/test/first
https://******.execute-api.eu-west-1.amazonaws.com/test/second
From this URL, I want the resource named first or second in lambda. Here the test is the stage name where I deplou\y my API. I have multiple resources created from that I want to change the behavior of lambda. How could I do this? Any help would be appreciated.

You can reconstruct the full url from values in the Lambda function's events variable.
events['headers']['Host'] = '******.execute-api.eu-west-1.amazonaws.com'
events['requestContext']['stage'] = 'test'
events['path'] = '/first'
So altogether, you can get https://******.execute-api.eu-west-1.amazonaws.com/test/first from adding them together:
'https://' + events['headers']['Host'] + '/' + events['requestContext']['stage'] + events['path']
See the Lambda Proxy integration part of the AWS documentation for details on other info you get can out of the events variable.

Related

API Gateway not passing event to lambda from console?

I'm trying to call a basic lambda from my API Gateway console. The lambda has an input taken in by the event called filterBy.
I created a query string called filterBy however, when I try to invoke the lambda I get the error:
{errorMessage: {'statusCode': 500, 'body': '{"msg": "KeyError(\'filterBy\')"}'}}
Presumably because the piece of code in my lambda
event['filterBy'] is not finding a filterBy in the event. What do I need to do so that I can get the filterBy in the event from the API Gateway console? I understand this is probably quite simple but I surprisingly cannot find anything about this so any help would be appreciated.
Based on the integration type, approach can be vary.
1. Lambda custom integrations:
Looks like you are trying to use Lambda custom integrations. If that is the case you have to add a mapping template as below.
(under the Integration Request -> Mapping Templates --> Add mapping template)
{
"filterBy": "$input.params('filterBy')"
}
Please refer this article or this video for more info.
2. Lambda proxy integrations:
If you are using Lambada proxy integration (either as REST API or as HTTP APIs), then instead of event['filterBy'], you have to access the queryStringParameters first and then access the relevant query param.
event['queryStringParameters']['filterBy']
And another thing is: once you modify something in API GW, please make sure to deploy and wait some time before test. :)

Set the HTTP Endpoint URL value for REST API from AWS CDK

I am trying to have a serviceHost stage variable to be set for each request from API GATEWAY, exactly like picture attached below.
According to doc https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-set-stage-variables-aws-console.html we can have something like this from console, but since my app is totally on CDK so just wanted to figure out a way to have it configured through CDK itself.
Couldn't find that in https://docs.aws.amazon.com/cdk/api/latest/docs/#aws-cdk_aws-apigateway.IntegrationOptions.html or anywhere.
Is it possible to attain through CDK somehow.
You can set the stage variables when declaring a stage. As per the documentation:
import aws_cdk.aws_apigateway
my_stage = aws_cdk.aws_apigateway.Stage(
self,
"my_stage",
variables = {"serviceHost": "my_value"}
)

add CloudwatchEvent dynamically in AWS Lambda code

I have a Lambda function triggered by S3 file Put event.Now once the lambda is triggered i want to attach cloudwatch event(cron) to the same lambda in the code.Is it possible?
You need to do 2 things to accomplish this
Add a target(lambda) in the cloudwatch rule (cron)
Add permission in lambda to allow the rule to invoke the lambda
I don't have an exact code sample to give you, but the below snippets will have to be included in your function to achieve this -
import boto3
event_client = boto3.client('events')
event_response = event_client.put_targets(
Rule=RULENAME,
Targets=[{
'Id': 'A_UNIQUE_STRING',
'Arn': 'ARN_LAMBDA'
}]
)
lambda_client = boto3.client('lambda')
lambda_response = lambda_client.add_permission(
FunctionName="LAMBDA_NAME",
StatementId="A_UNIQUE_STRING",
Action="lambda:InvokeFunction",
Principal="events.amazonaws.com",
SourceArn="ARN_RULE"
)
ARN_LAMBDA should be something like - arn:aws:lambda:<aws-region>:<aws-account-number>:function:<lambda-name>
ARN_RULE should be something like - arn:aws:events:<aws-region>:<aws-account-number>:rule/<rule-name>
A_UNIQUE_STRING - you can generate something in your code which is meaningful and unique or just a random string.
You can refer the guides in the boto3 documentation of lambda and cloudwatch events for more details -
http://boto3.readthedocs.io/en/latest/reference/services/lambda.html#Lambda.Client.add_permission
http://boto3.readthedocs.io/en/latest/reference/services/events.html#CloudWatchEvents.Client.put_targets
This should be possible for non-streaming triggers but you need to handle the two different event types in code.
On the other hand it would be better to use two seperate Lambdas since you will be only paying for the usage.

Consuming RSS feed with AWS Lambda and API Gateway

I'm a newbie rails programmer, and I have even less experience with all the AWS products. I'm trying to use lambda to subscribe to and consume an rss feed from youtube. I am able to send the subscription request just fine with HTTParty from my locally hosted rails app:
query = {'hub.mode':'subscribe', 'hub.verify':'sync', 'hub.topic': 'https://www.youtube.com/feeds/videos.xml?channel_id=CHANNELID', 'hub.callback':'API Endpoint for Lambda'}
subscribe = 'HTTParty.post(https://pubsubhubbub.appspot.com/subscribe, :query=>query)
and it will ping the lambda function with a get request. I know that I need to echo back a hub.challenge string, but I don't know how. The lambda event is empty, I didn't see anything useful in the context. I tried formatting the response in the API gateway but that didn't work either. So right now when I try to subscribe I get back a 'Challenge Mismatch' error.
I know this: https://pubsubhubbub.googlecode.come/git/pubsubhubbub-core-0.3.html#subscribing explains what I'm trying to do better than what I just did, and section 6.2.1 is where the breakdown is. How do I set up either the AWS Lambda function and/or the API Gateway to reflect back the 'hub.challenge' verification token string?
You need to use the parameter mapping functionality of API Gateway to map the parameters from the incoming query string to a parameter passed to your Lambda function. From the documentation link you provided, it looks like you'll at least need to map the hub.challenge query string parameter, but you may also need the other parameters (hub.mode, hub.topic, and hub.verify_token) depending on what validation logic (if any) that you're implementing.
The first step is to declare your query string parameters in the method request page. Once you have declared the parameters open the integration request page (where you specify which Lambda function API Gateway should call) and use the "+" icon to add a new template. In the template you will have to specify a content type (application/json), and then the body you want to send to Lambda. You can read both query string and header parameters using the params() function. In that input mapping field you are creating the event body that is posted to AWS Lambda. For example: { "challenge": "$input.params('hub.challenge')" }
Documentation for mapping query string parameters

How do I pass GET parameters to my AWS Lambda function when using an HTTP endpoint?

I followed the example from here to set up a sample AWS Lambda function: http://docs.aws.amazon.com/lambda/latest/dg/get-started-step4-optional.html.
Then, I created an HTTP GET endpoint via AWS API Gateway. I can access the endpoint but I don't know how to pass that int myCount as a parameter.
I tried ?myCount=3 as a GET parameter but that didn't work.
Any help?
You need to setup a mapping template in API Gateway. If you know the name of your parameters ahead of time your template could look like this:
{
"myCount": "$input.params('myCount')",
"myUserId": "$input.params('myUserId')"
}
Where each $input.params('...') will get evaluated and the value in your query string will be put in its place when the event is passed to Lambda.
This is pretty much a duplicate of passing query params for aws lambda function
In order to send HTTP parameters to a lambda function, they need to be sent in the request body via a mapping template.
See this blog post for a simple example of how to do this.
This is another way to do it:
Open API Gateway, select your endpoint and click on Resources
Select Method Request in the settings
Under the URL Query String Parameters, you can add query string.
As an example, in my Python lambda function, I can retrieve the query parameter just with the following:
def endpoint(event, context):
my_parameter = event["queryStringParameters"]