AWS API Gateway with Terraform
Published: 2022-01-20 11:49:57

__Most of the projects start as a monolith and then, in time, comes the part where we start splitting it in the “microservices” we all love. With this change in architecture there will be a part of your code that will start to look like a router, where it receives some request from the outside world and proceeds to redirect it to whoever is responsible for answering it. The AWS API Gateway is here so, we can lift those concerns from your service. We can even add more cross-cutting concerns to it (like authentication or rate limiting). Having this approach will even help with the latency of your response as it will skip the step of interpreting code to know were it should go, because it’s doing it directly in the AWS API Gateway.
Enough chit-chat and let’s get some coding done, starting with the creation of the api entry:
`resource “aws_api_gateway_rest_api” “api” {
 name = “api-gateway”
 description = “Proxy to handle requests to our API”`
}
In here we are creating the REST API resource to where all the requests are going to hit. Next we will start to configure what we want this API to do:
`resource "aws_api_gateway_resource" "resource" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  parent_id   = "${aws_api_gateway_rest_api.api.root_resource_id}"
  path_part   = "{proxy+}"
}
resource "aws_api_gateway_method" "method" {
  rest_api_id   = "${aws_api_gateway_rest_api.api.id}"
  resource_id   = "${aws_api_gateway_resource.resource.id}"
  http_method   = "ANY"
  authorization = "NONE"
  request_parameters = {
    "method.request.path.proxy" = true
  }
}
resource "aws_api_gateway_integration" "integration" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  resource_id = "${aws_api_gateway_resource.resource.id}"
  http_method = "${aws_api_gateway_method.method.http_method}"
  integration_http_method = "ANY"
  type                    = "HTTP_PROXY"
  uri                     = "http://your.domain.com/{proxy}"
 
  request_parameters =  {
    "integration.request.path.proxy" = "method.request.path.proxy"
  }
}`
Let’s do this in small steps so it’s clearer what is happening here.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ghsk1g6uel9fn9hfholb.png)
 
**Resource**
This is where we’ll configure on what endpoint are we listening for requests. The path_part argument will contain a string that represents the endpoint path, as our case is a simple proxy, AWS provides a special handler to listen all the requests, the "{proxy+}". This handler can also be applied to a more specific path, i.e "users/{proxy+}" where it will listen to anything starting with users ( i.e users/1/posts , users/3/notes , etc). The other values presented in there are related to where will this resource be applied, the rest_api_id will have the id of what API we are mounting this resource and the parent_id has the id of the parent on where are mounting this. This last one can be mounted directly on the root api (as we have) or mounted in another resource making it a child resource that will be composed by both parent and child. So if you have the path_part defined as "active" in the child resource and it’s mounted in the users resource, the child resource will listen to a users/active endpoint.

**Method**

In the method resource is were we build the specification of the endpoint we are listening. The http_method argument will have the string with what HTTP method we’re interested, the "ANY" value is, again, a special handler where we’ll accept any HTTP method that comes our way. In the case we have in hands we won’t need any authorization done in our AWS API Gateway, and that’s why the value in authorization is "NONE" . The request_parameters argument, will state that we will have something in a proxy handler required for this method and that will passed to the integration resource (described next).This resource also has some arguments related to where it should be mounted, namely the rest_api_id that is the same as the one described in the Resource resource and the resource_id that represents to what resource it should be related to.
**Integration**

The integration resource is related to how are we going to react to the request that we just received, it could go from passing the request to a backend, run some lambda function or even doing nothing with it. Besides the arguments previously referenced ( rest_api_id and resource_id ), we have the http_method argument that will be the same as the method resource (that’s why we link both of them with the "${aws_api_gateway_method.method.http_method}" ), the integration_http_method argument represents the HTTP method that will be done from the integration to our backend (again the "ANY" value is a special one) and we have the type argument where we configure what type of integration this is. As for the uri argument it will contain the endpoint to where we are proxying to, and the request_paramenters argument will map what we need from the method resource to our request to the backend, in our case we are are replacing the {proxy} handler present in the uri argument with the path that comes after the domain of our API Gateway.
The way that all of this can be grouped together is that a method and a integration are wrapped around a resource, the method will be responsible on how can the API Gateway be reached and the integration will be responsible in interacting with the backend. Kinda like this:

AWS API gateway working 🎉 If we go to                
`https://api-gateway.execute-api.{region}.amazonaws.com` (the {region} is the region where you’ll deploy the API, i.e eu-west-1) we’ll be communicating with our API Gateway.