Serverless Backends With AWS Cloud: API Gateway And You
Tags: apigateway, apicli, postman, awslambda
Published: 2017-04-24 19:06:44

---
title: "Serverless Backends With AWS Cloud: API Gateway And You"
published: true
description: Time to hook up our lambdas to the web at large
cover_image: 
tags: API Gateway, API CLI, Postman, AWS Lambda
---

_This is a part in a series on AWS serverless architecture. The original blog post series can be found both here and on my blog [J-bytes](http://robsherling.com/jbytes/index.php/2017/01/08/serverless-backends-with-aws-cloud-intro/)._

# Syncing The Gateway

The api gateway has two things you should know about it.

Integration Response manipulation is a twisted nightmare when combined with regexes if you aren't very meticulous.
It has no built-in version control of any kind.
We are going to use it manage our lambdas. Buckle up.

After each time that you successfully deploy and test a stage (more on that in a second), I am assuming that you are wisely exporting that stage as a swagger/yaml file and saving that in your version control from your local machine. Version control, every time. It won’t save your files from being seemingly randomly deleted, but it can make reconstruction much faster.

We are going to make a gateway that points to multiple versions of a lambda function (our staging and production aliased versions that we made last time). This will require the use of the AWS CLI and stage variables.

Open the API gateway tab. Click __get started__.

Click the __New API__ radio button on the top of the page.
This api is going to handle all of the calls for our site (email, twitter, etc), so let’s call it something that we want to use for our site. I’ll call mine __services-api__ (you can call it anything, though).

Click __Create API.__

Click on our newly-created __services-api__. Click the resources button. Your screen should look like this.

![api gateway new api screen](http://robsherling.com/jbytes/wp-content/uploads/2017/01/Screen-Shot-2017-01-09-at-16.40.31.png)

Click on __Create Resource__ and type __api__ in the resource path. Then click the blue __Create Resource__ button.

With our newly-created api resource selected, create another resource. Your screen should look like this (note the default Resource Path choice is automatically proceeded by /api/. This is good).

![create API Gateway resource menu](http://robsherling.com/jbytes/wp-content/uploads/2017/01/Screen-Shot-2017-01-09-at-16.43.28.png)

for the resource name, write __email__. Create Resource.

Select the newly-created email resource, then click __create method__ and choose POST from the dropdown.

![API Gateway POST menu dropdown](http://robsherling.com/jbytes/wp-content/uploads/2017/01/Screen-Shot-2017-01-09-at-16.45.25.png)

Click the checkmark to confirm. For integration type, choose lambda function. Leave the checkbox unticked and choose the region where your lambda is.  For the lambda function name, type `email_service:${stageVariables.alias}` and click save. DO NOT PANIC.

What you are seeing is AWS saying that you must manually approve certain API Gateway and Lambda connections. Unfortunately, because we want the staging API to go to our staging-aliased lambdas, and the production api to go to our production lambdas, we need to save the lambda alias in an stage-level variable and use that to dynamically call the appropriate lambdas. If that sounds very confusing, it's because it is. When you see it, it will become much clearer. Because this could be used to let any stage call any lambda, we have to go in and manually approve which aliases are allowed to be called from our stages. Let's do that now.

Install, if you have not already, your AWS CLI tools (google it for your machine, it is very straightforward). After you've done that (and configured them), copy that big blurb of panic text in the dark gray box into your terminal, but don't hit enter just yet. Change the part that says `email_service:${stageVariables.lambdaAlias}` to `email_service:staging` and hit enter. You should see some output that starts with the word __Statement__. Paste the same code again / hit up to access previous input, and now change it to read `email_service:production`. Hit enter again. Observe again response that starts with __statement__.

Now we've made the basic connection to our lambda and we need to configure a bunch of stuff before we can test it.

Back in the AWS panel, after you clicked __okay__ to confirm that you did the manual confirmation, click on the __post__ section under email. You should see this screen:


~![API Gateway General Screen Overview](http://robsherling.com/jbytes/wp-content/uploads/2017/01/Screen-1.png)


Click on __Integration Request__ in the upper-right hand corner. Click the __Body Mapping Templates__ dropdown and then change the __Request body passthrough__ option to __When there are no templates defined (recommended)__.

Click the blue __+__ to add a mapping type.
I am making the assumption that your site is stored in static files in S3 and configured to serve content that way, so we will need application/x-www-form-urlencoded. If you expect JSON here, you can use application/json here, but then you probably don't want to return 301 redirects either because it might be AJAX and need to edit your code appropriately.

Add the __application/x-www-form-urlencoded__ and click the check. Scrolling down slightly, you will see a drop-down box that says __Generate template__. Set it to __Method Request Passthrough__ and hit save.

Go back to the screen in the screenshot above (Method Execution panel), and click __Method Response.__
Click __add response__, and type in __301__. Click the check mark. Then click the drop-down arrow that appears next to 301. Click __add header__, and type __Location__. Click the check mark.

Go back to the method execution panel again, and click __Integration Response__. Delete the existing response, then click __Add integration response__.

For the lambda error regex, write `^Email.MovedPermanently.*`[(source)](https://aws.amazon.com/jp/blogs/compute/redirection-in-a-serverless-api-with-aws-lambda-and-amazon-api-gateway/). You could write a host of other regexes depending on what you want to capture. In English, that method was what AWS officially recommends and the only I could find, but if you aren't going to have multiple types of redirects/errors, .\* works just fine as a regex [(source)]( http://qiita.com/takyam/items/1789b4bea02f608e7a05).
For the method response status, choose the 301 that we made earlier.
Save, then expand the drop-down of our newly-created Integration Response. Under Header Mappings, where it says Response header with a value of Location, write in the value box __integration.response.body.errorType__. Click the check box, then the blue save button.

Go back to the Method Execution Panel, and change the drop-down inside Integration Response for HTTP status patter to the regex we just made (you may need to refresh the page).

Click the actions drop-down:


![API Gateway actions dropdown](http://robsherling.com/jbytes/wp-content/uploads/2017/01/actions-deploy-api.png)


Click __Deploy API__. In the popup, under Deployment stage we're going to select __[New Stage]__. For stage name, type __Staging__. For the descriptions, whatever you please. Hit deploy.

You will now see the staging stage. Click the __Stage Variables__ tab. Click __add stage variable.__ For Name, type __alias__. For Value, type __staging__. Click the checkmark.

This is where our `email_service:${stagingVariables.alias}` comes into play from earlier. This is how we tell the staging API to call email_service:staging alias.

Click Resources on the left-hand side, then Actions, then deploy API. Click new stage again, and set the name to production. Go Stage Variables, click Add Stage Variable, and use __alias__ and __production__ for the key and value. Note: Whenever you redeploy, you don't have to reset stage variables.

This should conclude our setup, so let's back this up to a yaml file. We actually also have the  option of backing it up as JSON, but (and I kid you not) because we didn't select application/json as our mapping type, it breaks the API if we try to restore from that file. No warnings, no errors, just breaks. If that is not your experience, please let me know; I'd hate to be bad-mouthing the API gateway if it was only my error.

Go to the export tab, click Export as Swagger + API Gateway Extensions, and copy the yaml and paste it in version control. You can restore from this if you ever need to by clicking resource -> actions -> import API.

We now have our api gateway setup. Let's test it: Fire up Postman.

If you want to see the URL you need to post to, simply click Stages on the left-hand side, then click the stage you are interested in. In that drop-down, click the green POST method under /api/email. The link next to Invoke URL is what you need to post to. In Postman, set your body to x-www-form-urlencoded, then for your key write __email__ and the value is whatever test email you want to confirm with.

Send, and you should get a glorious redirect. If you don't see the html for your website callback in the redirect, observe the following:

Response of missing authentication token -> URL is mistyped or https errors (should be no https errors possible yet, so almost always the url at this stage)
Internal server error but lambda works (You have logs and an email) -> API integration response regex or location mapping for the header has a typo.
Internal server error and no email -> ??? If you have this but your test for the lambda we built last chapter works, something went really, really wrong and you might want to redo a lot of this chapter.
That concludes the API gateway connection part! If you send a post to the staging vs production, it should call different lambdas!

Next, we'll set up cool twitter stuff to tweet in real time and follow some twitter accounts.