Menu
Amazon API Gateway
Developer Guide

Build an API Gateway API with Lambda Proxy Integration

In this section, we show how to create and test an API with the Lambda integration using the API Gateway console. We demonstrate how a Lambda backend parses the raw request and implements app logic that depends on the incoming request data. For more information on API Gateway proxy integration, see Set up a Proxy Integration with a Proxy Resource.

First, we create the following Node.js function, named GetStartedLambdaProxyIntegration, using the AWS Lambda console, as the backend. We then create an API with the Lambda proxy integration by using the GetStartedLambdaProxyIntegration function through a proxy resource by using the API Gateway console. Finally, we demonstrate how to test the API.

Create Lambda Functions for an API with Lambda Proxy Integration

We create a Lambda function that returns a greeting to the caller as a JSON object of the following format:

Copy
{ "greeting": "Good {time}, {name} of {city}.[ Happy {day}]" }

In this example, {time} can be morning, afternoon, or day; {name} can be you or a user-specified user name; {city} can be World or a user-supplied city name; and {day} can be null, empty, or one of the week days. If {day} is null or empty, the Happy {day} portion is not displayed. The Lambda function is very flexible and the client can specify the input in any combination of request headers, path variables, query string parameters, and body.

To show what API Gateway passes through to the backend, we include the event object to the Lambda function in its output as well. Finally, we create a response object to illustrate the basic output format required of the Lambda proxy integration.

A Lambda function can be written in Node.js, Python, Java, and C#. In this tutorial, we show snippets in Node.js and Java. You can extend the Node.js implementation to the Python function or extend the Java implementation to the C# function. There are instructions for doing so in the following topics.

Node.js Function for an API with Lambda Proxy Integration

The following Lambda function in Node.js is a "Hello, World!" application. The function shows how to parse the input event parameter that contains a request made by a client to an API Gateway proxy resource. This resource is integrated with the function using the Lambda proxy integration. The function also demonstrates how to format the output of the Lambda function for API Gateway to return the results as an HTTP response. For more information about the input and output formats that this type of Lambda function must follow, see Input Format of a Lambda Function for Proxy Integration and Output Format of a Lambda Function for Proxy Integration.

Copy
'use strict'; console.log('Loading hello world function'); exports.handler = function(event, context, callback) { let name = "you"; let city = 'World'; let time = 'day'; let day = ''; let responseCode = 200; console.log("request: " + JSON.stringify(event)); // This is a simple illustration of app-specific logic to return the response. // Although only 'event.queryStringParameters' are used here, other request data, // such as 'event.headers', 'event.pathParameters', 'event.body', 'event.stageVariables', // and 'event.requestContext' can be used to determine what response to return. // if (event.queryStringParameters !== null && event.queryStringParameters !== undefined) { if (event.queryStringParameters.name !== undefined && event.queryStringParameters.name !== null && event.queryStringParameters.name !== "") { console.log("Received name: " + event.queryStringParameters.name); name = event.queryStringParameters.name; } } if (event.pathParameters !== null && event.pathParameters !== undefined) { if (event.pathParameters.proxy !== undefined && event.pathParameters.proxy !== null && event.pathParameters.proxy !== "") { console.log("Received proxy: " + event.pathParameters.proxy); city = event.pathParameters.proxy; } } if (event.headers !== null && event.headers !== undefined) { if (event.headers['day'] !== undefined && event.headers['day'] !== null && event.headers['day'] !== "") { console.log("Received day: " + event.headers.day); day = event.headers.day; } } if (event.body !== null && event.body !== undefined) { let body = JSON.parse(event.body) if (body.callerName) name = body.callerName; } let greeting = 'Good ' + time + ', ' + name + ' of ' + city + '. '; if (day) greeting += 'Happy ' + day + '!'; var responseBody = { message: greeting, input: event }; // The output from a Lambda proxy integration must be // of the following JSON object. The 'headers' property // is for custom response headers in addition to standard // ones. The 'body' property must be a JSON string. For // base64-encoded payload, you must also set the 'isBase64Encoded' // property to 'true'. var response = { statusCode: responseCode, headers: { "x-custom-header" : "my custom header value" }, body: JSON.stringify(responseBody) }; console.log("response: " + JSON.stringify(response)) callback(null, response); };

For the API Gateway proxy integrations, the input parameter of event contains an API request marshalled as a JSON object by API Gateway. This input can include the request's HTTP method (httpMethod), path (path and pathParameters), query parameters (queryStringParameters), headers (headers), and applicable payload (body). The input can also include the context (requestContext) and stage variables (stageVariables).

This example Lambda function parses the event parameter to retrieve the query string parameters of name and httpStatus.

The function then returns a greeting to the named user in the message property of the responseBody object. To show the details of the incoming request as marshalled by API Gateway, the function also returns the incoming event object as the input property of the response body.

Finally, upon exiting, the function returns a JSON object, containing the required statusCode and any applicable headers and body, for API Gateway to return it as an HTTP response to the client.

Python Function for an API with Lambda Proxy Integration

Follow the discussion in Authoring Lambda Functions in Python to create the Python Lambda function handler, while extending the programming flow shown in the preceding Node.js Lambda function.

C# Function for an API with Lambda Proxy Integration

Follow the discussion in Authoring Lambda Functions in C# to create the C# Lambda function handler, while extending the programming flow shown in the following Java Lambda function.

Java Function for an API with Lambda Proxy Integration

The following Lambda function in Java is a "Hello, World!" application, similar to its Node.js counterpart. The function shows how to parse the input event that is passed through as an InputStream object and that contains a request made by a client to an API Gateway proxy resource. This resource is integrated with the function using the Lambda proxy integration. It also shows how to parse the context object to get the LambdaLogger. The example also demonstrates how to format the output of the Lambda function for API Gateway in Java to return the results in an OutputStream object as an HTTP response. For more information about the Lambda proxy integration input and output formats, see Input Format of a Lambda Function for Proxy Integration and Output Format of a Lambda Function for Proxy Integration.

Copy
package examples; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.BufferedReader; import java.io.Writer; import com.amazonaws.services.lambda.runtime.RequestStreamHandler; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.LambdaLogger; import org.json.simple.JSONObject; import org.json.simple.JSONArray; import org.json.simple.parser.ParseException; import org.json.simple.parser.JSONParser; public class ProxyWithStream implements RequestStreamHandler { JSONParser parser = new JSONParser(); public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException { LambdaLogger logger = context.getLogger(); logger.log("Loading Java Lambda handler of ProxyWithStream"); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); JSONObject responseJson = new JSONObject(); String name = "you"; String city = "World"; String time = "day"; String day = null; String responseCode = "200"; try { JSONObject event = (JSONObject)parser.parse(reader); if (event.get("queryStringParameters") != null) { JSONObject qps = (JSONObject)event.get("queryStringParameters"); if ( qps.get("time") != null) { time = (String)qps.get("time"); } } if (event.get("pathParameters") != null) { JSONObject pps = (JSONObject)event.get("pathParameters"); if ( pps.get("proxy") != null) { city = (String)pps.get("proxy"); } } if (event.get("headers") != null) { JSONObject hps = (JSONObject)event.get("headers"); if ( hps.get("day") != null) { day = (String)hps.get("header"); } } if (event.get("body") != null) { JSONObject body = (JSONObject)parser.parse((String)event.get("body")); if ( body.get("callerName") != null) { name = (String)body.get("callerName"); } } String greeting = 'Good ' + time + ', ' + name + ' of ' + city + '. '; if (day!=null || day != "") greeting += 'Happy ' + day + '!'; JSONObject responseBody = new JSONObject(); responseBody.put("input", event.toJSONString()); responseBody.put("message", greeting); JSONObject headerJson = new JSONObject(); headerJson.put("x-custom-response-header", "my custom response header value"); responseJson.put("statusCode", responseCode); responseJson.put("headers", headerJson); responseJson.put("body", responseBody.toString()); } catch(ParseException pex) { responseJson.put("statusCode", "400"); responseJson.put("exception", pex); } logger.log(responseJson.toJSONString()); OutputStreamWriter writer = new OutputStreamWriter(outputStream, "UTF-8"); writer.write(responseJson.toJSONString()); writer.close(); } }

For proxy integrations in API Gateway, the input stream contains an API request serialized as a JSON string by API Gateway. The input data can include the request's HTTP method (httpMethod), path (path and pathParameters), query parameters (queryStringParameters), headers (headers), applicable payload (body), the context (requestContext), and stage variables (stageVariables).

This example Lambda function parses the inputStream parameter to retrieve the query string parameters of name and httpStatus. For logging, it retrieves the LambdaLogger object from the incoming context object.

The function then returns a greeting to the named user in the message property of the responseBody object. To show the details of the incoming request as marshalled by API Gateway, the function also returns the input data (event) in the response body.

Finally, upon exiting, the function returns a JSON string, containing the required statusCode and any applicable headers and body, for API Gateway to return it as an HTTP response to the client.

To create this function in the Lambda console, you must create a deployment package before uploading the package into Lambda. For more information, see creating a deployment package in the AWS Lambda Developer Guide.

Create a Backend for an API with Lambda Proxy Integration

The following procedure describes how to create the Lambda function in API Gateway using the Lambda console.

Create a Lambda function for an API with a proxy resource in the Lambda console

  1. Sign in to the Lambda console at https://console.aws.amazon.com/lambda.

  2. From the upper-right corner, choose an available region for the Lambda function.

  3. From the main navigation pane, choose Functions.

  4. Choose one of the following procedures to create a Lambda function in Node.js or Java. You can adapt the instructions for other languages and platforms.

    1. To create the Node.js Lambda function, choose Create a Lambda function or Get Started Now to create your first Lambda function in a region, and then do the following.

      1. On the Select blueprint page, choose Author from scratch.

      2. On the Configure triggers page, choose Next.

      3. On the Configure function page, do the following:

        - Type a function name in the Name input field.

        - Type a brief function description in the Description input field.

        - From the Runtime drop-down list, choose Node.js 4.3.

      4. Under Lambda function code, do the following:

        - Choose Edit code inline from the Code entry type drop-down list.

        - Type or copy your Node.js code into the inline code editor.

      5. Under Lambda function handler and role, do the following:

        - Leave index.handler as-is for Handler.

        - Choose an existing or create a new IAM role for the function execution.

      6. Keep the default values for Advanced settings.

      7. Choose Next.

      8. In the Review pane, choose Create function.

      For this tutorial, use GetStartedLambdaProxyIntegration as the function name and choose the standard Simple Microservice permissions policy templates to create the required Lambda execution role.

    2. To create a Java Lambda function, choose Create a Lambda function or Get Started Now to create your first Lambda function in a region, and then do the following.

      1. On the Select blueprint page, choose Author from scratch.

      2. On the Configure triggers page, choose Next.

      3. On the Configure function page, do the following:

        - Type a function name in the Name input field.

        - Type a brief function description in the Description input field.

        - From the Runtime drop-down list, choose Java 8.

      4. Under Lambda function code, do the following:

        - Choose a Code entry type for uploading a deployment package from a local drive or Amazon S3.

        - Choose Upload next to Function package.

        - Navigate to the deployment package location and select the package.

      5. Under Lambda function handler and role, do the following:

        - Type your function handler of the package_name.function_name::method_name format in Handler.

        - Choose an existing or create a new IAM role for the function execution.

      6. Keep the default values for Advanced settings.

      7. Choose Next.

      8. In the Review pane, choose Create function.

      For this tutorial, use examples as the Java package name, use ProxyWithStreams as the Java class name, use handleRequest as the Java function name, and use examples.ProxyWithStreams::handleRequest as the Lambda function handler name. Choose the standard Simple Microservice permissions policy templates to create the required Lambda execution role.

Note

Note the region where you created the Lambda function. You need it when creating the API for the function.

Create an API with Lambda Proxy Integration

Now create an API with a proxy resource for a Lambda function by using the API Gateway console.

Build an API with a proxy resource for a Lambda function

  1. Sign in to the API Gateway console at https://console.aws.amazon.com/apigateway.

  2. To create an API, choose Create new API (for creating the first API) or Create API (for creating any subsequent API). Next, do the following:

    1. Choose New API.

    2. Type a name in API Name.

    3. Optionally, add a brief description in Description.

    4. Choose Create API.

    For this tutorial, use LambdaSimpleProxy as the API name.

  3. To create a child resource, choose a parent resource item under the Resources tree and then choose Create Resource from the Actions drop-down menu. Then, do the following in the New Child Resource pane.

    1. Select the Configure as proxy resource option to create a proxy resource. Otherwise, leave it de-selected.

    2. Type a name in the Resource Name* input text field.

    3. Type a new name or use the default name in the Resource Path* input text field.

    4. Choose Create Resource.

    5. Select Enable API Gateway CORS, if required.

    For this tutorial, use the root resource (/) as the parent resource. Select Configure as proxy resource. For Resource Name, use the default, proxy. For Resource Path, use /{proxy+}. De-select Enable API Gateway CORS.

  4. To set up the ANY method for integration with the Lambda back end, do the following:

    1. Choose the resource just created and then choose Create Method from the Actions drop-down menu.

    2. Choose ANY from the HTTP method drop-down list and then choose the check mark icon to save the choice.

    3. Choose Lambda Function Proxy for Integration type.

    4. Choose a region from Lambda Region.

    5. Type the name of your Lambda function in Lambda Function.

    6. Choose Save.

    7. Choose OK when prompted with Add Permission to Lambda Function.

    For this tutorial, use the previously created GetStartedLambdaProxyIntegration for the Lambda Function.

For the proxy resource API that Lambda just created, API Gateway forwards the raw request from the client to the backend for the Lambda function to process. The request includes the request method, its path, query string and headers parameters, any payload, plus context and stage variables. The next procedure describes how to test this.

Test an API with Lambda Proxy Integration

The following procedure describes how to test the proxy integration.

Call the GetStartedLambdaProxyIntegration Lambda function through the proxy resource

  • To use a browser to call a GET method on a specific resource of the API, do the following.

    1. If you have not done so, choose Deploy API from the Actions drop-down menu for the API you created. Follow the instructions to deploy the API to a specific stage. Note the Invoke URL that displays on the resulting Stage Editor page. This is the base URL of the API.

    2. To submit a GET request on a specific resource, append the resource path, including possible query string expressions to the Invoke URL value obtained in the previous step, copy the complete URL into the address bar of a browser, and choose Enter.

    For this tutorial, deploy the API to a test stage and note of the API's base URL; for example, https://wt6mne2s9k.execute-api.us-west-2.amazonaws.com/test.

    There are several ways you can test a deployed API. For GET requests using only URL path variables or a query string parameter, you can type the API resource URL in a browser. For other methods, you must use more advanced REST API testing utilities, such as POSTMAN or cURL.

    To test the deployed API using cURL

    1. Open a terminal window on your local computer connected to the internet.

    2. To test POST /Seattle?time=evening:

      Copy the following cURL command and paste it into the terminal window.

      Copy
      curl -v -X POST \ 'https://r275xc9bmd.execute-api.us-west-2.amazonaws.com/test/Seattle?time=evening' \ -H 'content-type: application/json' \ -H 'day: Thursday' \ -H 'x-amz-docs-region: us-west-2' \ -d '{ "callerName": "John" }'

      You should get a successful response with the following payload:

      Copy
      { "message": "Good day, John of Seattle. Happy Friday!", "input": { "resource": "/{proxy+}", "path": "/Seattle", "httpMethod": "POST", "headers": { "day": "Friday" }, "queryStringParameters": { "time": "morning" }, "pathParameters": { "proxy": "Seattle" }, "stageVariables": null, "requestContext": { "path": "/{proxy+}", "accountId": "123456789012", "resourceId": "nl9h80", "stage": "test-invoke-stage", "requestId": "test-invoke-request", "identity": { "cognitoIdentityPoolId": null, "accountId": "123456789012", "cognitoIdentityId": null, "caller": "AIDXXX...XXVJZG", "apiKey": "test-invoke-api-key", "sourceIp": "test-invoke-source-ip", "accessKey": "ASIXXX...XXDQ5A", "cognitoAuthenticationType": null, "cognitoAuthenticationProvider": null, "userArn": "arn:aws:iam::123456789012:user/kdeding", "userAgent": "Apache-HttpClient/4.5.x (Java/1.8.0_131)", "user": "AIDXXX...XXVJZG" }, "resourcePath": "/{proxy+}", "httpMethod": "POST", "apiId": "r275xc9bmd" }, "body": "{ \"callerName\": \"John\" }", "isBase64Encoded": false } }

      If you change POST to PUT in the preceding method request, you get the same response.

    3. To test GET /Boston?time=morning:

      Copy the following cURL command and paste it into the terminal window.

      Copy
      curl -X GET \ 'https://r275xc9bmd.execute-api.us-west-2.amazonaws.com/test/Seattle?time=evening' \ -H 'content-type: application/json' \ -H 'day: Thursday' \ -H 'x-amz-docs-region: us-west-2'

      You get a 200 OK Request response similar to the result from the preceding POST request, with the exception that the GET request does not have any payload. So the body parameter will be null.

    Note

    The requestContext is a map of key-value pairs and corresponds to the $context variable. Its outcome is API-dependent. API Gateway may add new keys to the map. For more information, see Input Format of a Lambda Function for Proxy Integration .