Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the name of the stage in an AWS Lambda function linked to API Gateway

I have the following Lambda function configured in AWS Lambda :

var AWS = require('aws-sdk');
var DOC = require('dynamodb-doc');
var dynamo = new DOC.DynamoDB();
exports.handler = function(event, context) {

    var item = { id: 123,
                 foo: "bar"};

    var cb = function(err, data) {
        if(err) {
            console.log(err);
            context.fail('unable to update hit at this time' + err);
        } else {
            console.log(data);
                context.done(null, data);
        }
    };

    // This doesn't work. How do I get current stage ?
    tableName = 'my_dynamo_table_' + stage;

    dynamo.putItem({TableName:tableName, Item:item}, cb);
};

Everything works as expected (I insert an item in DynamoDB every time I call it).

I would like the dynamo table name to depend on the stage in which the lambda is deployed.

My table would be:

  • my_dynamo_table_staging for stage staging
  • my_dynamo_table_prod for stage prod

However, how do I get the name of the current stage inside the lambda ?

Edit: My Lambda is invoked by HTTP via an endpoint defined with API Gateway

like image 703
Benjamin Crouzier Avatar asked Mar 23 '16 15:03

Benjamin Crouzier


People also ask

How do you find the stage variable in Lambda function?

In Stage description, type a description for your new stage, and then choose Deploy. To apply the change, deploy the API to a new stage called prod: Next, set up the stage variable in the new deployment stage to point to the second Lambda function, GetHelloWithName : Now you are ready to test!

What is stage name API gateway?

To deploy an API, you create an API deployment and associate it with a stage. A stage is a logical reference to a lifecycle state of your API (for example, dev , prod , beta , v2 ). API stages are identified by the API ID and stage name. They're included in the URL that you use to invoke the API.

What is stage in AWS API gateway?

A stage is a named reference to a deployment, which is a snapshot of the API. You use a Stage to manage and optimize a particular deployment. For example, you can configure stage settings to enable caching, customize request throttling, configure logging, define stage variables, or attach a canary release for testing.


2 Answers

If you have checked "Lambda Proxy Integration" in your Method Integration Request on API Gateway, you should receive the stage from API Gateway, as well as any stageVariable you have configured.

Here's an example of an event object from a Lambda function invoked by API Gateway configured with "Lambda Proxy Integration":

{
"resource": "/resourceName",
"path": "/resourceName",
"httpMethod": "POST",
"headers": {
    "header1": "value1",
    "header2": "value2"
},
"queryStringParameters": null,
"pathParameters": null,
"stageVariables": null,
"requestContext": {
    "accountId": "123",
    "resourceId": "abc",
    "stage": "dev",
    "requestId": "456",
    "identity": {
        "cognitoIdentityPoolId": null,
        "accountId": null,
        "cognitoIdentityId": null,
        "caller": null,
        "apiKey": null,
        "sourceIp": "1.1.1.1",
        "accessKey": null,
        "cognitoAuthenticationType": null,
        "cognitoAuthenticationProvider": null,
        "userArn": null,
        "userAgent": "agent",
        "user": null
    },
    "resourcePath": "/resourceName",
    "httpMethod": "POST",
    "apiId": "abc123"
},
"body": "body here",
"isBase64Encoded": false
}
like image 116
JS1010111 Avatar answered Sep 28 '22 11:09

JS1010111


I managed it after much fiddling. Here is a walkthrough:

I assume that you have API Gateway and Lambda configured. If not, here's a good guide. You need part-1 and part-2. You can skip the end of part-2 by clicking the newly introduced button "Enable CORS" in API Gateway

Go to API Gateway.

Click here:

enter image description here

Click here:

enter image description here

Then expand Body Mapping Templates, enter application/json as content type, click the add button, then select mapping template, click edit

enter image description here

And paste the following content in "Mapping Template":

{
  "body" : $input.json('$'),
  "headers": {
    #foreach($param in $input.params().header.keySet())
    "$param": "$util.escapeJavaScript($input.params().header.get($param))" #if($foreach.hasNext),#end

    #end  
  },
  "stage" : "$context.stage"
}

Then click the button "Deploy API" (this is important for changes in API Gateway to take effect)

You can test by changing the Lambda function to this:

var AWS = require('aws-sdk');
var DOC = require('dynamodb-doc');
var dynamo = new DOC.DynamoDB();

exports.handler = function(event, context) {
    var currentStage = event['stage'];

    if (true || !currentStage) { // Used for debugging
        context.fail('Cannot find currentStage.' + ' stage is:'+currentStage);
        return;
    }

// ...
}

Then call your endpoint. You should have a HTTP 200 response, with the following response body:

{"errorMessage":"Cannot find currentStage. stage is:development"}

Important note:
If you have a Body Mapping Template that is too simple, like this: {"stage" : "$context.stage"}, this will override the params in the request. That's why body and headers keys are present in the Body Mapping Template. If they are not, your Lambda has not access to it.

like image 24
Benjamin Crouzier Avatar answered Sep 28 '22 11:09

Benjamin Crouzier