You have a database now, and you've got a lambda, you'll need access to these from the outside. For this let's build an AWS API Gateway. This will expose a REST api to the outside that anyone can reach, if they know the url. In this tutorial you'll secure it with a secret client api key, so it will only respond to you. Everyone else gets an error if they try to use it.
Also, we're going to create 2 different "stages" for your API Gateway, one called dev
and one called prod
. This will
allow the API Gateway to execute a different version of your lambda function, depending on which url is used (as the
dev and prod urls will be a little different). You'll use the dev
and prod
aliases you set up for your lambda in
the last page of instructions.
Having two different "stages" like this means that you can assign a stable version of your lambda for use in
production, on user's devices after your capsule has been released to the marketplace. And you'll still be able to
continue to work on bug fixes and improvements, in newer versions of your lambda and Bixby Studio using the dev
url,
without disturbing current users.
Here's how to create your API Gateway service:
- go the API Gateway Service
- look on the top line of the console, make sure that you have selected the same AWS region that you used for the lambda and the database
- press the blue
Create API
button - if it asks you to create an example api for the pet store (because this is your first api), click
Ok
- select
New API
(instead ofExample API
, if necessary, see image below) - enter an API name, like
memory-api
(this name could be anything, as it's not referenced anywhere else) - press the
Create API
button
You need to create the top-level resource for your api:
- pull down the
Actions
menu and chooseCreate Resource
- enter a resource name and resource path (use
service
for both) - leave the CORS checkbox unchecked
- press the
Create resource
button
Now create a POST method on this resource:
- pull down the
Actions
menu and chooseCreate method
- choose POST from the menu that appears
- enter the name of the lambda function, as
memory-lambda
- press the
Save
button - press
Ok
when a popup window asks you about providing access to the lambda function
You'll need the API to accept JSON data, follow these steps to create a mapping:
- after the last step, you should be at the service POST page (see image below)
- click on the
Integration Request
link
- scroll down until you can see
Mapping Templates
(see image below) - click on the triangle to expand this section
- click on the + button to add a mapping template
- enter
application/json
into the content-type field - press the checkmark button
- when a popup comes through about changing passthrough behavior, press the
Yes, secure this integration
button
- scroll down further so you can see the generate template dropdown menu
- choose
Method Request passthru
from the menu
- once the code fills into the window, press the
Save
button
- return to the POST method page once again by clicking on the
Method Execution
link
Once your capsule is released, you are going to need separate development and production environments. That
allows you to work on new features without affecting current users. When you set up memory-lambda
, you created
aliases for dev
and prod
. Now let's create two deployment stages in your AWS API Gateway, one for each.
Here's how:
- select the root level in your api navigation sidebar (if it's not already selected)
- pull down the
Actions
menu - choose
Deploy API
(see image below)
- select
[New Stage]
for the Deployment stage (see image below) - enter
dev
for the State name - press the
Deploy
button
- select the
Stage Variables
tab (see image below) - press the
+
button next to Add Stage Variable
- enter the variable name
env
(see image below) - enter the value
dev
- press the checkbox
- click on the
memory-api
->Resources
link in the sidebar - repeat the process above to deploy another stage, but this time use
prod
, instead ofdev
When you are done, you will have two deployment stages, dev
and prod
, and each wil have a stage environment
variable called env
that has a value equal to the stage name.
Now we'll make the API Gateway call a different version of the lambda, using an alias, depending on which deployment stage is used. Try this:
- click on the
memory-api
->Resources
link in the sidebar (see image below) - expand the api service by clicking on the triangle
- click on the
POST
operation - click on the
Integration Request
link
- click on the pencil icon to edit the name of the lambda function that you entered earlier (see image below)
- modify the name of the lambda function from
memory-lambda
tomemory-lambda:${stageVariables.env}
(see image below) - click on the checkbox
A popup window will appear, warning you that you need to give the API Gateway permission to call the lambda using both of the new aliases. Do the following:
- copy all of the text from the pink background section into the clipboard (see image below, I've blocked out own account number)
- note the location of the new lambda function call (the red rectangle in the image below)
- open a terminal window where you have cmdline AWS access configured for this account (from the AWS setup earlier)
- paste the clipboard text onto the command line
- edit the command line, replacing
${stageVariables.env}
withdev
and press return (see image below) - paste the clipboard text onto the command line again
- edit the command line, replacing
${stageVariables.env}
withprod
and press return
You may test that the api calls the lambda properly for each stage, by taking the following steps:
- click on the
memory-api
->Resources
link in the sidebar (see image below) - click in the
POST
method in the navigation sidebar - press the
Test
link
- enter
dev
for the value of the env state variable (see image below, you may useprod
instead if you like) - enter the following JSON into the request body:
{
"secretClientApiKey": "my-client-key-0425-afgnrq-4fe6h1",
"clientVersion": "1.0.0",
"userId": "my-unique-user-001",
"actionType": "list"
}
- press the
Test
button - after the test runs, you'll be able to to see the output on the right of the image below, the Response Body should look similar to what you saw when you tested the lambda earlier
Note: the request gets wrapped in a body-json
object by the Gateway API mapping function. That's why the code
in index.js
looks for the request body within a body-json
property. You may remember that When you tested from the
lambda earlier, you needed to wrap the request with a body-json
object. You don't need to do that when testing
from the Gateway API, nor when using the new REST api from the outside.
To find the url for accessing your api from outside AWS, look at the stage information:
- click on the link in the left-most navigation bar that says
Stages
- click on
dev
orprod
- note that the URL is displayed at the top (I blocked out the account identifier in the image below)
To use the URL, you'll need to add a forward-slash and the name of the resource we added, which was service
.
And it can only be called with POST. We'll test it from outside AWS, in the next section.
It's best to test your REST api now, to work out any bugs, before you try using it from a capsule. Try this:
- download and install Postman
- run Postman and click on the
Request
link in the welcome window to create a new request (see image below)
- give the request a name, like
AWS Tutorial Request
(see image below) - click on
Create Collection
and enter a collection name, likeAWS Tutorial
, and click on the checkbox - press the
Save to AWS Tutorial
button
- on the new request page, where it says
GET
, choosePOST
instead for the operation type (see image below) - enter the URL for the Gateway API, remember to add
/service
to the URL that you copied from the Gateway API page above - click on the
Body
tab - under the body tab, click on
raw
- to the right of
raw
, where it saysText
, chooseJSON (application/json)
from the dropdown menu instead - paste the same JSON data into this request that you used to test the Gateway API earlier:
{
"secretClientApiKey": "my-client-key-0425-afgnrq-4fe6h1",
"clientVersion": "1.0.0",
"userId": "my-unique-user-001",
"actionType": "list"
}
- click on the
Save
button - click on the
Send
button
You should see results like those below:
For more information about all of this, see these excellent articles that explain how this works in more detail: