Creating a REST endpoint with API Gateway
The course is part of these learning paths
The first steps in creating a serverless function are generally creating a REST interface to allow clients to interact with your backend services. In this course, we step through creating an API using the AWS API Gateway service.
So to get started with our journey to the land of Lambda, we're gonna create a new API Gateway first to get an idea of how this works. So first we'll create a new API. Once we've defined this new API, we can then see how we connect it to our AWS Lambda function. Now doing this provides an easy way to create a scalable backend for a modern application or mobile app. We can configure our custom stages, protect resources with an API key and explain how to best connect API Gateway stages within AWS Lambda version and alias. One of the main use cases for AWS Lambda is that you can attach a RESTful interface to it through the Amazon API Gateway. And in the serverless world, a typical configuration looks similar to this. We may have a static website hosted on Amazon S3 and distributed via Amazon CloudFront. We have a RESTful API implemented with AWS Lambda and HTTP end points exposed via the Amazon API Gateway service. Behind that, we have dynamic data stored in Amazon DynamoDB, Amazon RDS or other databases as a service that may be serving as an alternative. This is how you build a completely serverless web application, meaning that you won't need to manage, patch or maintain any server during your development and deployment workflow. The level of abstraction provided by a RESTful API should guarantee a uniform interface and a set of stateless interactions. Now this means that all the information necessary to process a request must be included in the request itself. I.e., the URL, the headers, the query string or the body. And furthermore, each resource should be eventually cacheable by the client based on the particular use case. So this approach is particularly useful when you consider that each request and response can be attached to a custom mapping template in order to perform custom data manipulation or improve API backward compatibility. And that's all good, but building that type of stateless interface on your own isn't easy, right? So the beauty of the AWS API Gateway service is that it provides an easy way to create RESTful application programmable end points. The API Gateway makes it easy to design your own resources and structure, add dynamic routing parameters and develop custom authorizations logic. Each API resource can be configured independently, while each stage can have a specific cache, throttling and logging configurations. Most relevant for us right now is that the API Gateway interfaces can connect to a Lambda function from right here within the AWS console. Perfect. With Amazon API Gateway, you can define resources, map them to custom models, specify which methods are to be made available, i.e. if it's going to be POST or GET, et cetera. And eventually, you can bind each method to a particular Lambda function. Alternatively, you can attach more than one method to each Lambda function. We can design a very simple API to read a list of items and retrieve the details of a given item by its ID. To do this, we'll define two HTTP end points. We'll do one, which is /items, and that will return all the items we define. We'll do another path, which we'll call /item/ID, which will pull back a specific item based on the ID parameter we pass to it. These routes are compliant with the RESTful design principles. The first endpoint lets you retrieve the full list of items, while the second one corresponds to the detail of a single item given its ID. The second needs to be a subset of the first, so they're on the same path. The second route is a little different in that it is defined by a dynamic parameter, which we will make part of the URL itself. So what we are doing with the second route is similar to what we might have done in the past using a query string with a parameter, e.g., we might have a /items, question mark, id=1 for example. Now we can present our URL just like this with API Gateway if we wanted to, but one of the benefits of the API gateway service is that we can hide a lot of the things like the file name and the extension. API end point is more secure and generally less prone to compromise, so it's a better way of presenting values to a requesting client. So first of all, we're going to need to create this new API. Now beneath the Application Services menu, we can click on the API Gateway section. Here we can click on Get Started or Create API. Now the new API name we'll call itemsAPI. Let's fill out the name and description fields. Then we'll create by clicking Create API. The first thing we need to do in this form is define an API Gateway model. Now the order of things in Lambda is important. So let's just make sure we understand what this idea of a model is. Gateway models are useful to map your API end points, basically via mapping templates. Now having a model is not mandatory. You can manually define your mapping templates. But having a model will let you generate strongly typed SDKs for you API resources. And more importantly, I think, to better validate your payloads. I like to imagine that my API Gateway is a bouncer that I've hired for my daughter's 21st birthday party. This bouncer is renowned as being an excellent security specialist, really great at protecting the door and getting rid of uninvited guests, if need be. However, our guests are from a range of cultural backgrounds. So for our bouncer to work well with our guest list, they need to know and be provided with as much guidance as possible on how to greet and welcome and talk to this wide variety of guests that we're expecting for our party. Now this is sort of how the API Gateway works. API Gateway needs to know the model of interaction that you want and the method for how to deal with requests. For example, it could be a handshake, it could be a high five or it could be a curtesy or a bow. It can be anything you want, you just need to tell the bouncer how to recognize and when to do either of those based on preference. In order to define a new item model, we fill out the model name and the content type. So this idea of content type can throw you a bit. The most common application type is this one, application/json, or J-S-O-N. Now that means the interface will read the import text that's provided to it as a JSON-formatted text doc. This definition tells the client how to pass the content it is about to receive. So first off, with our application declaration, we're asking the bouncer to communicate in JSON. Okay, so now we can define what we want this API document model to do. We can then define some simple object types for our API. First we declare the object. Now this model we'll use to display items from a catalog that we'll create. So let's just enter some of these values. We'll enter our schema type in which we just refer to json-schema.org. We give it a title. We give it a type. And we can define some properties, namely an ID, which is a type number; and name, which is a type string; and a price, which we'll make a type number. Okay. Now after we click the Create Model button, the new item model will be listed beneath the models that show up in the left navigation. Now that we have a model for our item list, we need to create a subordinate model for requesting individual items based on that ID variable to select one item from the catalog rather than to pull back the entire list. So what we do next is create a new items model with the following information. We'll give it an ID field, title and the type being the array, which will be the array of items. And the items will reference using the URL from our existing API. The name of our API, we can find in the top bar, you'll see up here. So this is our API that pulls back all of our items. The AWS API Gateway console is super cool as it will catch most format errors for you. And I notice it will generally fail to save if you declare something really stupid. So we can now see both item and items beneath the model, or models, in the left navigation. Now we need to create our API resources and their methods. The order of things is important when you're creating API Gateway functions. So now that we've defined the model, we need to define the resources that it's going to use. To do this, we click the Resources tab in the left navigation pane. Then Actions, Create Resource. Let's create a new resource named itemsList. This will be the items we want to present to any requester who has been allowed through the door basically. The resource name and path we define do not need to be the same so we can define a unique path for our items list resource. So let's set our path to the friendly name /items. We can leave both the proxy resource and the enable API Gateway calls function unchecked for now, Which is their default values. And we'll get back into what these options can do for us later. Now we'll notice that there are no methods created yet. So the order of things is important. So remember, we've defined our model, we define our resource then the method for that resource. Now the method is the business end of what this API will do. So now we need to define the method for this resource, and that's decided in our method declaration. If you declare it, the API makes it so. Let's get some methods for our API. First let's select the /items resource that we just created. Let's add a new GET method by selecting it, and then Actions, Create Method. We select GET from the drop-down menu and then click Confirm. So at this point, it looks like we have a working gateway. Remember, the API is designed to only respond to things that we tell it to respond to. The integration request is the incoming request. We can set ours to be mock data only. So we can mess around with it as much as we like, and this is a great feature of API Gateway. It gives us the scratchpad to try out our API to make sure it's working before we're actually running or presenting any real data. The graphic we see on the screen at this point will start to make more sense the more you practice creating gateways. Right now, it can look a little confusing as it has four request pathways. A shortcut answer is to remember to navigate to the integration response method first. So the advantage of this is we can use our items model to generate fake data. For example, this would allow us to provide a temporary API end point to our front end or mobile developers, even before we have a real implementation so they can use it and test it out. So we'll select the Integration Response box, click the right arrow to expand the 200 response status. Expand the Body Mapping Templates section and click on application/json, J-S-O-N. Here you can automatically generate a mapping template by selecting our items model from the drop-down menu in the generate template field. If we have more than one model, it will show up in this drop-down. So AWS will generate a mapping template with random fake data, based on our JSON schema. So given that our model defines a list, the template would generate a foreach loop we can customize before we save it. So we could use the default template test, or we can create our own. So for each ID in an array of one, two and three, we'll give it a price based on the ID times 1.5. And we'll give it a name plus an ID value. And then we'll just response the ID, the name and the price. And loop through each of those. So we can quickly test this API method going method execution test, and then we can click the Test button. Okay, so we've successfully created our first API gateway. And gateway will return the data set when it's requested independent of any variable or condition. So now let's create our second gateway. And this time, we'll set a parameter field so that we can request a specific record based on the ID, rather than returning the entire data set. So let's create a new resource named item, and we'll give it a path/items/ID. Now given the hierarchical structure of these end points, we need to create a sub resource. Remember that you will need to insert only the ID part of the URL since we've already created the /items resource. Since we want the second part of the URL to be dynamic, we're going to define that part as a variable, brackets ID. Now this way, API Gateway will retreat any value as a dynamic ID and pass it back to our backend implementation. And that will return the corresponding data. Now as we've done already, let's create a GET method for this with a mock integration. Then we can use the item model in the integration response template mapping. Our implementation might look like this. We'll give it an integer value of one, and we'll pass the param, which in this case is our ID field. We'll set our name to be plus ID, and our price being the ID times 1.6. And then we response our ID and name and our price. So this template will extract the dynamic ID parameter casted into an integer and return an item object with fake generated data. So at this point, we can test our new /items/ID resource as we did previously. But this time, we'll need to enter a value under the ID field before clicking the Test button. Now if we leave the ID field blank, we'll get an internal server error response. And I've seen plenty of those in some of my earlier testing. So as I said, we'll try and remember the order of things with API Gateway and make sure that you do understand each of the models, resources and methods required to create one of these. Now remember, it's just simple mock implementation data so we can replace this with a real implementation in our next steps. Now theres one critical thing that we need to do and one you need to keep reminding yourself to make sure you do this, and that's deploying the API. So when we're ready to deploy this and test it in our browser, we actually need to set a deploy action. So we go select Actions, Deploy API. And then we create a new deployment stage. When we're ready, we can click Deploy. The API should now be deployed and ready to serve requests at the /items where it will return all the items and /items/ID parameter, where it will return only the requested ID.
About the Author
Head of Content
Andrew is an AWS certified professional who is passionate about helping others learn how to use and gain benefit from AWS technologies. Andrew has worked for AWS and for AWS technology partners Ooyala and Adobe. His favorite Amazon leadership principle is "Customer Obsession" as everything AWS starts with the customer. Passions around work are cycling and surfing, and having a laugh about the lessons learnt trying to launch two daughters and a few start ups.