Menu
Amazon API Gateway
Developer Guide

Create an API Gateway API as an AWS Lambda Proxy

If your API makes only synchronous calls to Lambda functions in the back end, you can use the Lambda Function integration type. This is a special case of the AWS Service integration type, where API Gateway simplifies the Lambda integration set-up for you with default settings. They include, for example, granting resource-based permissions to invoke the Lambda function. For instructions, see Build an API to Expose a Lambda Function.

If your API makes asynchronous calls to Lambda functions, you must use the AWS Service integration type described in this section. With the AWS Service integration type, you have more control and, hence, more responsibility to set up the integration. The set-up instructions apply to requests for synchronous Lambda function invocations as well. For the asynchronous invocation, you must explicitly add the X-Amz-Invocation-Type:Event header to the integration request. For the synchronous invocation, you can add the X-Amz-Invocation-Type:RequestResponse header to the integration request or leave it unspecified. The following example shows the integration request of an asynchronous Lambda function invocation:

Copy
POST /2015-03-31/functions/FunctionArn/invocations?Qualifier=Qualifier HTTP/1.1 X-Amz-Invocation-Type: Event ... Authorization: ... Content-Type: application/json Content-Length: PayloadSize Payload

In this example, FunctionArn is the ARN of the Lambda function to be invoked. The Authorization header is required by secure invocation of Lambda functions over HTTPS. For more information, see the Invoke action in the AWS Lambda Developer Guide.

To illustrate how to create and configure an API as an AWS service proxy for Lambda, we will create a Lambda function (Calc) that performs addition (+), subtraction (-), multiplication (*), and division (/). When a client submits a method request to perform any of these operations, API Gateway will post the corresponding integration request to call the specified Lambda function, passing the required input (two operands and one operator) as a JSON payload. A synchronous call will return the result, if any, as the JSON payload. An asynchronous call will return no data.

The API can expose a GET or POST method on the /calc resource to invoke the Lambda function. With the GET method, a client supplies the input to the back-end Lambda function through three query string parameters (operand1, operand2, and operator). These are mapped to the JSON payload of the integration request. With the POST method, a client provides the input to the Lambda function as a JSON payload of the method request, which is then passed through to the integration request. Alternatively, the API can expose a GET method on the /calc/{operand1}/{operand2}/{operator} resource. With this method, the client specifies the Lambda function input as the values of the path parameters. Parameter mappings and mapping templates are used to translate the method request data into the Lambda function input and to translate the output from the integration responses to the method response.

This section provides more detailed discussions for the following tasks:

  • Create the Calc Lambda function to implement the arithmetic operations, accepting and returning JSON-formatted input and output.

  • Expose GET on the /calc resource to invoke the Lambda function, supplying the input as query strings.

  • Expose POST on the /calc resource to invoke the Lambda function, supplying the input in the payload.

  • Expose GET on the /calc/{operand1}/{operand2}/{operator} resource to invoke the Lambda function, specifying the input in the path parameters.

You can import the sample API as a Lambda proxy from the Swagger Definitions of a Sample API as Lambda Proxy. To do so, copy the Swagger definition, paste it into a file, and use the API Gateway Swagger Importer. For more information, see Getting Started with the API Gateway Swagger Importer.

To use the API Gateway console to create the API, you must first sign up for an AWS account.

If you do not have an AWS account, use the following procedure to create one.

To sign up for AWS

  1. Open https://aws.amazon.com/ and choose Create an AWS Account.

  2. Follow the online instructions.

To allow the API to invoke Lambda functions, you must have an IAM role that has appropriate IAM policies attached to it. The next section describes how to verify and to create, if necessary, the required IAM role and policies.

Set Up an IAM Role and Policy for an API to Invoke Lambda Functions

The API will use the InvokeFunction action to call a Lambda function. At minimum, you must attach the following IAM policy to an IAM role for API Gateway to assume the policy.

Copy
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "lambda:InvokeFunction", "Resource": "*" } ] }

If you do not enact this policy, the API caller will receive a 500 Internal Server Error response. The response contains the "Invalid permissions on Lambda function" error message. For a complete list of error messages returned by Lambda, see the Invoke topic.

An API Gateway assumable role is an IAM role with the following trusted relationship:

Copy
{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": "apigateway.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }

Create a Lambda Function in the Back End

Copy the following Lambda function and paste it into the code editor in the Lambda console.

Copy
exports.handler = function(event, context, callback) { //console.log('Received event:', JSON.stringify(event, null, 2)); var res = {}; res.a = event.a; res.b = event.b; res.op = event.op; switch(event.op) { case "+": res.c = Number(event.a) + Number(event.b); break; case "-": res.c = Number(event.a) - Number(event.b); break; case "*": res.c = Number(event.a) * Number(event.b); break; case "/": res.c = Number(event.b)===0 ? NaN : Number(event.a) / Number(event.b); break; default: res.c = "Invalid op"; } callback(null, res); };

This function requires two operands (a and b) and an operator (op) from the event input parameter. The input is a JSON object of the following format:

Copy
{ "a": "Number" | "String", "b": "Number" | "String", "op": "String" }

This function returns the calculated result (c) and the input. For an invalid input, the function returns either the null value or the "Invalid op" string as the result. The output is of the following JSON format:

Copy
{ "a": "Number", "b": "Number", "op": "String", "c": "Number" | "String" }

You should test the function in the Lambda console before integrating it with the API, which is created next.

Create API Resources for the Lambda Function

The following procedure describes how to create API resources for the Lambda function.

To create API resources for Lambda functions

  1. In the API Gateway console, create an API named LambdaGate. You can create child resources to represent different Lambda functions; in the following, you will create a single child resource of the API root.

  2. For the simple calculator function you created, create the /calc resource off the API's root. You will expose the GET and POST methods on this resource for the client to invoke the back-end Lambda function, supplying the required input as query string parameters (to be declared as ?operand1=...&operand2=...&operator=...) in the GET request and as a JSON payload in the POST request, respectively.

    You will also create the /calc/{operand1}/{operand2}/{operator} to expose the GET method to invoke the Lambda function and to supply the required input as the three path parameters (operand1, operand2, and operator).

    We will show how to apply API Gateway request and response data mapping to normalize the input to the back end Lambda function.

    
                                Create an API in API Gateway as a Lambda proxy

Create a GET Method with Query Strings to Call the Lambda Function

Use the following steps to expose a GET method with query strings to call a Lambda function.

To set up the GET method with query strings to invoke the Lambda function

  1. Choose Create Method in the API Gateway console to create a GET method for the API's /calc resource.

    In the method's Set up pane, configure the method with the following settings.

    
                                Set up a method for integration with Lambda

    You must use the POST method for the integration request when calling a Lambda function, although you can use any other HTTP verbs for the method request.

    The Path override value must the URL path of the Lambda Invoke action. The path is of the following format:

    Copy
    /2015-03-31/functions/FunctionName/invocations?Qualifier=version

    where FunctionName is the ARN of the Lambda function to be invoked. The optional Qualifier query string can be used to select a version of the function. If it not specified, the $LATEST version will be used.

    You can also add the X-Amz-Invocation-Type: Event | RequestReponse | DryRun header to have the action invoked asynchronously, as request and response, or as a test run, respectively. If the header is not specified, the action will be invoked as request and response. For the example shown here, this header has the default value.

    We will come back to setting up a mapping template for the request payload in the Body Mapping Templates section after setting up the query string parameters to hold the input data for the Lambda function.

  2. In Method Request for the GET method on /calc, expand the URL Query String Parameters section. Choose Add query string to add the operand1, operand2, and operator query string parameters.

    
                                Set up a method request URL query strings for integration
                                    with Lambda

  3. Go back to Integration Request. Expand the Body Mapping Templates section. Choose When no template matches the request Content-Type header for Request body passthrough. If application/json is not shown under Content-Type, choose Add mapping template to add it. And then type and save the following mapping script in the mapping editor:

    Copy
    { "a": "$input.params('operand1')", "b": "$input.params('operand2')", "op": "$input.params('operator')" }

    The result of this step is illustrated as follows:

    
                                Map a method request URL query strings to integration
                                    request payload to call Lambda function

    This template maps the three query string parameters declared in Method Request into designated property values of the JSON object as the input to the back-end Lambda function. The transformed JSON object will be included as the integration request payload.

  4. You can now choose Test to verify that the GET method on the /calc resource has been properly set up to invoke the Lambda function.

Create a POST Method with a JSON Payload to Call the Lambda Function

The following steps describe how to expose a POST method with a JSON payload.

To set up the POST method with a JSON payload to invoke a Lambda function

  1. Choose Create Method in the API Gateway console to create a POST method for the LambdaGate API's /calc resource.

    In the method's Set Up panel, configure the POST method with the following settings.

    
                                Set up the POST method to invoke the Lambda function

    Using a POST request with a JSON payload is the simplest way to invoke a Lambda function, because no mappings are needed.

  2. You can now choose Test to verify the POST method works as expected. The following input:

    Copy
    { "a": 1, "b": 2, "op": "+" }

    should produce the following output:

    Copy
    { "a": 1, "b": 2, "op": "+", "c": 3 }

If you would like to implement POST as an asynchronous call, you can add an InvocationType:Event header in the method request and map it to the X-Amz-Invocation-Type header in the integration request, using the header mapping expression of method.request.header.InvocationType. You must inform the clients to include the InvocationType:Event header in the method request. Alternatively, you can set the X-Amz-Invocation-Type header with the 'Event' string literal in the integration request, without requiring the client to include the header. The asynchronous call will return an empty response, instead.

Create a GET Method with Path Parameters to Call the Lambda Function

The following steps describe how to set up the GET method with path parameters to call the Lambda function.

To set up the GET method with URL path parameters to invoke the Lambda function

  1. Choose Create Method in the API Gateway console to create a GET method for the API's /calc/{operand1}/{operand2}/{operator} resource.

    In the method's Set up pane, configure this GET method with the following settings.

    
                                Set up the GET method with path parameters to invoke the
                                    Lambda function

    Next, we will set up Body Mapping Templates to translate the URL path parameters into the integration request JSON payload as the input to the Lambda function.

  2. In Method Request for the GET method on /calc/{operand1}/{operand2}/{operator}, expand the Request Paths section to verify that the path parameters are there.

    
                                Verify a method request path parameters for integration with Lambda

  3. Go back to Integration Request. Expand the Body Mapping Templates section.

    Choose When no template matches the request Content-Type header for Request body passthrough.

    If necessary, add application/json under Content-Type by choosing Add mapping template.

    Type the following in the body mapping template editor:

    Copy
    { "a": "$input.params('operand1')", "b": "$input.params('operand2')", "op": #if($input.params('operator')=='%2F')"/"#{else}"$input.params('operator')"#end }

    This template maps the three URL path parameters, declared when the /calc/{operand1}/{operand2}/{operator} resource was created, into designated property values of the JSON object. Because URL paths must be URL-encoded, the division operator must be specified as %2F instead of /. This template maps these translations as well. The transformed JSON object will be included as the integration request payload.

    
                                Map a method request URL path parameters to the integration
                                    request payload to call the Lambda function

  4. As another exercise, we demonstrate how to translate the JSON returned from the Lambda function to show the output as a plain text string to the caller. This involves resetting the method request's Content-Type header to "text/plain" and providing a mapping template to translate the JSON output into a plain string.

    First, make sure that Content-Type header is included in the Response Headers for 200 section in Method Response.

    
                                Declare method response header to be overridden in
                                    integration response

  5. In Integration Response, expand the 200 method response entry. Expand the Header Mappings section. In Mapping value for Content-Type, type 'text/plain'. This header mapping expression overrides the Content-Type header with a literal string, which must be enclosed within a pair of single quotes.

    
                                Map integration response body and header from JSON to plain
                                    text

    Next, expand the Body Mapping Templates section, choose the application/json entry under the Content-Type header (of integration response) to open the mapping template editor, enter and save the following mapping script:

    Copy
    $input.path('$.a') $input.path('$.op') $input.path('$.b') = $input.path('$.c')
  6. Choose Test to verify the GET method on the /calc/{operand1}/{operand2}/{operator} works as expected. The following request URL:

    Copy
    /calc/1/2/%2F

    should produce the following plain text output:

    Copy
    1 / 2 = 0.5

    Note

  7. After testing the API using the Test Invoke in the API Gateway console, you must deploy the API to make it public available. If you update the API, such as adding, modifying or deleting a resource or method, updating any data mapping, you must redeploy the API to make the new features or updates available.