Benjamin Crouzier
Benjamin Crouzier

Reputation: 41855

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:

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

Upvotes: 20

Views: 13502

Answers (4)

Divyansh Singh
Divyansh Singh

Reputation: 401

You can get it from event variable. I logged my event object and got this.

{  ...
    "resource": "/test"
    "stageVariables": {
        "Alias": "beta"
    }
}

Upvotes: 1

Benjamin Crouzier
Benjamin Crouzier

Reputation: 41855

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.

Upvotes: 10

JS1010111
JS1010111

Reputation: 617

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
}

Upvotes: 19

yishaiz
yishaiz

Reputation: 2583

For those who use the serverless framework it's already implemented and they can access to event.stage without any additional configurations.

See this issue for more information.

Upvotes: 4

Related Questions