Generic Amazon API Gateway Java Client (SDK)

I’ve just built apigateway-generic-java-sdk, a simple generic Java client for Amazon API Gateway endpoints for those that don’t necessarily want to generate a strongly-typed SDK. This is particularly useful when the API definition is changing rapidly or when you don’t want to go through the effort of generating and bundling an SDK, such as when prototyping or scripting.

It is optimized to run from a Lambda function and does not require any extra dependencies beyond the AWS SDK, which is already bundled in the Lambda runtime.

Features

  • AWS SigV4 request signing. Supports APIs authenticated with IAM auth using standard AWSCredentialsProvider interface
  • API Keys
  • Custom headers
  • Throws exceptions for non-2xx response codes
  • Compatibility with existing AWS SDK client configuration (connections, retry policies, etc)
  • Runs in AWS Lambda functions with no additional dependencies

Example

To get the code and for more examples, see the GitHub repo.

How to send response headers for AWS Lambda function exceptions in API Gateway

In a previous post on error handling in API Gateway I discussed various ways to map errors from your Lambda function to appropriate API status codes and how to build the response body appropriately for different types of errors.

One common pattern we’ve seen come up is the requirement to return a specific response header value depending on the type of error from the Lambda function. While this is most easily achieved with proxy integrations, some prefer to use the explicitly-mapped “AWS” integration type. This allows their Lambda function implementation to use native error types and decouples it from their API Gateway configuration.

In this example I will show how to manipulate the HTTP status code, the response body, as well as a response header value based on the Lambda error outcome.

Note, this example is specific to the NodeJS runtime, and will only allow to set a single header – please post in the comments if you have similar solutions for other runtimes.

This technique makes use of the fact that Lambda serializes the exception type in the errorType field, which can be mapped to a header value in API Gateway. This is a workaround solution until API Gateway supports JSON-parsing in parameter mapping expressions.

Lambda function

Observe that this Lambda function sets the error.name field to the value desired in the response header. When the error is serialized by Lambda, this becomes the “errorType” field in the Lambda response. You can also set custom properties in the Lambda error which can be used when rendering the API response body.

This Lambda function outputs the following response:

API definition

Note that the method response header is set to the value of the “errorType” field in the Lambda error response for 400 responses.

Zooming in on the mapping template for the 400 response:

The “stringified” errorMessage is parsed by the mapping template so that all properties (including custom properties) of the error object can be accessed in the mapping template to build the response body.

Invoking this method produces the following results, appropriately setting the trifecta of status code, response body, and response header.

Comments, questions, and improvements are welcome!

-Ryan

Bare-bones Swagger Example for API Gateway Simplified Proxy Features

Amazon API Gateway just made it a LOT easier to build an API to front an existing HTTP backend or Lambda functions.

Recent additions of a few simple but powerful new features reduce the amount of configuration needed to build an API Gateway proxy by several times. No more mapping templates, parameter mapping, response mappings, etc. (unless you need them).

Here’s a super simple example demonstrating the 3 new features (greedy path parameter, “ANY” method, and proxy integration types).

This API will accept requests using any HTTP method to any subpath of any depth under either /http or /lambda. Any request under /http will proxy all headers, path parameters, and query string parameters to the HTTP integration (httpbin.org). Any request under /lambda will invoke a Lambda function with complete API request data in accordance with the proxy convention defined here.

Easy API Gateway/Lambda “Serverless” API Logging/Debugging

Developing and testing “serverless” APIs using Amazon API Gateway and AWS Lambda can be made much easier with built-in support for CloudWatch Logs.

In Lambda functions you can use log statements to send log events to CloudWatch Log streams, and API Gateway automatically submits log events for requests to APIs with logging enabled.

However, it can be difficult to reconcile log events for a serverless API sent across multiple CloudWatch log groups and log streams. Tracking down logs for a specific request or tailing request logs for a serverless API can be a cumbersome experience.

To help improve the serverless dev/debug/test experience, I’ve released a fork of the excellent awslogs project to include native support for API Gateway/Lambda serverless APIs. Given an API Gateway REST API ID and Stage name, this tool produces an aggregated stream of time-ordered*, color-coded log events emitted by API Gateway and all Lambda functions attached to your API. The log events can then be further filtered and processed by standard command-line tools.

i.e. stream all log events emitted from API Gateway as well as from all Lambda functions attached to the API:

or search APIG/Lambda logs for events from a specific request ID in the past hour:

Tip: To correlate API Gateway request IDs with Lambda invocations, send $context.requestId to your Lambda function via a mapping template and include it in your Lambda log messages (i.e. console.log(event.apiRequestId + ” – log message”);)

Check out ‘apilogs’ here. Fixes and contributions are greatly appreciated.

Happy debugging!
Ryan

An API Gateway mapping template to “send everything” to your Lambda function

If you’re trying to get up to speed with developing microservices on API Gateway and Lambda, one of the first things you will want to try is to send basic API request data to your Lambda function.

Since all Lambda function input data must go in the request body, you must use an API Gateway mapping template to build a JSON representation of your data.

Here’s a master template to “send everything” API Gateway provides (as of 02/22/2016) to your Lambda function. This should serve as a good starting point and can be modified to suit your use-case. This will include all HTTP parameters, context data, stage variables, and the full method request body.

Here’s a Gist with the code.

For more information, check out the API Gateway mapping template reference.

Cheers,

Ryan

How To: HTTP redirects with API Gateway and Lambda

API Gateway recently released support for mapping response bodies to response headers. One application of this feature is to enable conditional HTTP redirects in your API Gateway/Lambda API.

There are a couple of ways to achieve 30x redirects in your API Gateway/Lambda API.

Option 1: 30X as “default” response

This option is preferred if your API method always redirects (i.e. never returns a normal 2XX response).

1) Define a method response with status 302, and a “Location” header defined
2) Define a “default” integration response mapping with blank regex, mapping to 302.
3) For this response, define a “Location” header mapping from the redirect URL returned in your Lambda function. i.e. “integration.response.body.location”
3) Configure your lambda function to return the redirect location in the body, i.e.

Swagger example

Lambda function

Option 2: 30X as an error response

This option allows your method to return both “successful” (2XX) and redirect outcomes, but requires you to model redirects in your lambda function as errors.

1) Define a method response with status 302, and a “Location” header defined. Leave the “default” integration 2XX response with blank regex, mapped to your 2XX method response.
2) Define the redirect integration response mapping with regex “http.*”, mapped to your 30X response.
3) For this response, map the redirect URL returned in the error message of your lambda function to your “Location” header: “integration.response.body.errorMessage”
3) Configure your lambda function to return the redirect location as the error message, i.e.

or

4) Optional: If you don’t want to expose the lambda error response body to the client, define a mapping template on the redirect response to nullify the response body. You can use a template with a comment to render an empty response.

Swagger example

Lambda function

Here’s a full Gist with the example.

Cheers,
Ryan

Sending all HTTP parameters in API Gateway

Here’s an API Gateway mapping template to send all HTTP path, query string, and header parameters to your backend integration (i.e. Lambda function).

will produce something like:

The parameters can then be accessed in your Lambda function, i.e.

Here’s a Gist with the example.

Cheers,
Ryan