How to validate requests in Amazon API Gateway
Tags: apigateway, serverless, cloudcomputing, aws
Published: 2024-06-30 21:39:19

In this article, I will share my experience validating requests in Amazon API Gateway. First, let's start with why you need to validate requests at the API Gateway level.
One of the key features of Serverless architecture is its cost-efficient model (pay-per-use). By following best practices, validating requests at the API Gateway level is a good idea for efficiency and security. It's also worth noting that API Gateway does not charge for unauthorized or invalid requests. When an endpoint is invoked with a bad request, API Gateway intercepts and rejects the request, returning a 400 status code to the user.

API Gateway is a fully managed AWS service that makes it easy for developers to create, publish, maintain, monitor, and secure APIs at any scale.

## API Gateway Model and RequestValidator Class
 We can request validation from API Gateway by using the `RequestValidator` in `api-gateway` module from the `aws-cdk-lib` library.

### Code Sample:

```
const requestValidator = new RequestValidator(
      this,
      "RequestValidator",
      {
        restApi: api,
        requestValidatorName: "requestBodyValidator",
        validateRequestBody: true,
        validateRequestParameters: false,
      }
    );
```

The props:
- restApi: The string identifier of the associated RestApi. (api) is a reference to the API Gateway instance.
- requestValidatorName: The name of this RequestValidator.
- validateRequestBody: A Boolean flag indicating whether to validate the request body according to the configured _Model schema_.
- validateRequestParameters: A Boolean flag indicating whether to validate request parameters (true) or not (false).

The `RequestValidator` helps set up basic validation rules for incoming requests to the API. To validate the request body, we need to set up a `Model` schema. The Model schema defines the structure of a request or response payload for an API method.

### Creating a Model Schema

Let's create a Model schema for an API Gateway request validator that includes `firstName`, `lastName`, and `portfolioLink` as properties.

### Code Sample:

```
const validatorModel = new Model(this, "RequestValidatorModel", {
      restApi: api,
      contentType: "application/json",
      description: "Validate Long Url",
      modelName: "ValidatorModel",
      schema: {
        schema: JsonSchemaVersion.DRAFT4,
        title: "ModelValidator",
        type: JsonSchemaType.OBJECT,
        properties: {
          firstName: {
            type: JsonSchemaType.STRING,
            minLength: 1,
          },
          lastName: {
            type: JsonSchemaType.STRING,
            minLength: 1,
          },
          portfolioLink: {
            type: JsonSchemaType.STRING,
            pattern: "^(http://|https://|www\\.).*",
          }
        },
        required: ["firstName", "lastName"],
      },
    });
```

In this `Model`, we defined `firstName` and `lastName` as required properties in the request payload with a minimum length of 1. We also defined `portfolioLink` of type String and enforced a specific regex pattern.

The Props:
- `restApi`: The string identifier of the associated RestApi - (api) is a reference to API Gateway instance.
- `contentType`: The content type for the model. By default, it is 'application/json', so if you are configuring for text, it will be 'text/HTML'.
- `description`: A string that identifies the model.
- `modelName`: A name for the model. By default, AWS CloudFormation generates a unique physical ID and uses that ID for the model name.
- `schema`: The schema to use to transform data to one or more output formats. In API Gateway models are defined using the JSON schema draft 4. 
- `title`: Defines the schema title.
- `type`: Specifies that the root of the JSON document must be an object.
- `properties`: Defines the properties the object must have.
- `required`: A list of properties that must be present in the object. In our case, `firstName` and `lastName`.

### Attaching the Model and Validator to an API Gateway Method

Next, we need to attach our `Model` and `RequestValidator` to an API Gateway method.

### Code Sample:

```
api.root
      .addResource("/user")
      .addMethod("POST", user, {
        requestModels: {
          "application/json": validatorModel,
        },
        requestValidator: requestValidator,
      });
```

By following these steps, you can efficiently validate requests at the API Gateway level, ensuring that only properly structured requests reach your backend services. This not only improves security but also reduces unnecessary processing and potential costs.