Lab 2: API
Exercise: API
Story So Far
It's early, but with freshly brewed coffee ☕️ at hand. All is good in the world.
You are ready to start day two of your project.
So far, you have a working website but it doesn't do anything clever (yet).
Mike walks past your desk, and gives you an approving nod. He seems happy with your progress so far.
Today, you are determined to really impress Mike, by making this thing interactive. You are going to build out a backend API.
As you know (if you did the optional stage 4 of Lab 1) your website starts up and checks for the existence of an API endpoint. If an endpoint remains as null
in the config file. Then the site will tell you that you have no API to call. If however, you do provide an API endpoint in your config file, the website will attempt to connect with it.
As you will see in a bit, it is wired up in such a way that it will handle a specific type of response from the back end.
So this is your game plan for today.
Setup an API gateway stage, with three (3) distinct API routes. That's one for each site function
get_reviews
,get_ratings
andcreate_report
. Each of these functions will return hard coded MOCK data that the front end is geared up to handle.📓 Regardless of what product Id is passed in the request, it's going to get the same canned response.
You will then confirm that all 3 routes work, via the API GW console testing feature.
You will need to set up CORS on one of the API routes (
create_report
) because the website is CROSS domain from the API endpoint.💁♂ For the simple GET requests, you do not need to configure all the OPTIONS settings to make AJAX calls. You only need to enable CORS on the more "involved" POST request, where we are
going to behandling Cognito Authentication.Once you publish the API stage, you will test that the website is displaying the mock data correctly.
Finish strong, with a frappe on your way home.
What you will learn in this lab:
How to create an API GW resource with 3 routes using the SDK of your choosing.
Learn how to test your API in the API GW test console, and learn how to navigate around the AWS API GW console. Check for settings such as the method execution and any integration response configuration.
You will learn how to enable CORS (Cross Origin Resource Sharing) on a route (again via the SDK).
Before you start
Let's take a moment to think about how you are going to set up all this mock data.
Each of these API's will need to be provided with mock data in a format that the website can react to.
Let's look at the type of mock data we are taking about.
If they choose "get ratings", we will have our backend API respond with this hard coded value (again regardless of the product ID passed).
Request
Response (Status 200)
This is going to be your "canned" response because the website is expecting this sort of structure.
For the "ratings" functionality, which is going to provide the average rating across a product's set of reviews. You will have something more like this:
Request
Response (Status 200)
This is going to be your "canned" response.
Finally for the create_report functionality.
💁♂ This third API is actually really simple (for now that is ;)....evil laugh. All it does is say "got it cheers", then proceeds to do absolutely nothing else.
Like so:
Request
Response (Status 200)
This is going to be your "canned" response.
💁♂ You can ignore the check your phone thing...that's not happening. Later on, in future labs this API call will trigger a background process, and send a report out to their cell.
Ok, so now you know what your API needs to do. It's time to actually create it all.
You will use start off by using a script called mock
which will build out the core API. You will be using the SDK of your choice.
Accessing the AWS Management Console
At the top of these instructions, click Start Lab to launch your lab.
A Start Lab panel opens displaying the lab status.
Wait until you see the message "Lab status: ready", then click the X to close the Start Lab panel.
At the top of these instructions, click AWS
This will open the AWS Management Console in a new browser tab. The system will automatically log you in.
TIP: If a new browser tab does not open, there will typically be a banner or icon at the top of your browser indicating that your browser is preventing the site from opening pop-up windows. Click on the banner or icon and choose "Allow pop ups."
Arrange the AWS Management Console tab so that it displays along side these instructions. Ideally, you will be able to see both browser tabs at the same time, to make it easier to follow the lab steps.
Setup
Ensure you are in Cloud9. Choose Services and search for Cloud9. You should see an existing IDE called Building_2.0. Click the button Open IDE. Once the IDE has loaded, enter the following command into the terminal: (This command will ensure that you are in the correct path)
You will need get the files that will be used for this exercise. Go to the Cloud9 bash terminal (at the bottom of the page) and run the following
wget
command:Unzip:
Let's cleanup:
Run the
resources/setup.sh
script that will grab the website contents and upload them to the S3 bucket created by our CloudFormation template.⚠️ If you are using Java you will also need to run the following scripts and commands:
Lab Steps
Stage 1 - Create A New API GW using the SDK
🔬 Open the
mock
file in your chosen language folder. Read through it so you know what it's doing.⚠️ If you are using Java the folder structure for java is different from for Node.js or Python. You'll need to navigate to the parent folder for the program to run. The parent folder name will correspond with the file name for the other languages. In this case, the file is named
mock
for node and python, therefore the folder you should navigate to in the java folder is themock
folder. Under that folder you should see apom.xml
file - that is how you know you are in the right spot :)💁♂ If you are not in the right right folder in the
CMD_LINE
, navigate to it now.For example if you are using Python use
cd python_3.6.8
The following table shows the respective run command needed to run the
mock
file:Language
Filename You Need To Edit
Command to run via
CMD_LINE
Node.js (v10)
mock.js
npm install aws-sdk && node mock.js
Python (v3)
mock.py
python3 mock.py
Java
App.java
mvn clean install && mvn exec:java -Dexec.mainClass=com.mycompany.app.App
Once you run the file in the
CMD_LINE
you should see (regardless of language) the word done.📓 A lot is happening when you run this
mock
file. So please take a moment to read though it and see what it is doing, before moving on.📓 One thing worth talking about in the mock file is the method and integration settings:
How does the API handle the query string?
By using this as the integration response we can tell our respective GET routes to capture a "predefined" value
"$input.params('product_id')",
. This is going to come in from the query string and map it to a variable name for the output. Namelyproduct_id_str
.When we say "predefined", we are referring to where we declare it first in our method request parameters. As seen below:
That bit allows us to reference the
product_id
phrase in our integration response as above, and thus translate (or map) it to a variable that we can use later in our Lambda code. In this caseproduct_id_str
.The
false
flag is just saying that we are not going to validate the existence of that query string key. 💁♂ Otherwise you would have to set up separate validators for both GET APIs, which for this lab is probably overkill.Final note: For a MOCK you want to pass everything through as OK for the Integration request, like so.
They are the main areas of note.
💁♂ For many of you who have worked with API GW before and are perhaps used to having Lambda Proxy just send everything though to the final end point, you might be wondering "why bother doing this mapping stuff". There is no wrong or right way of approaching API Gateway with a backend, there are just different approaches. Either way I think is it useful for you to see your options and how all this integration and method stuff works.
With all that said, how do even know that our script even worked?
Stage 2 - Testing the API
Head over to the AWS console for API GW. Ensure Fancy-APi
exists (we're great at naming things in this team), and test it, as follows.
Choose AWS Cloud9 and Go To Your Dashboard. Choose Services and API Gateway. There should be a
Fancy-Api
that was created by thatmock
script. Choose theFancy-Api
. Make sure you are in us-west-2.📓 It is important that you have a browse around the API GW console, to see what your script created. Check the settings for GET Method Request URL Query String Parameters and the GET - Integration Request application/json mappings as as expected.
Let's test
get_reviews
first. Choose the GET method underget_reviews
.Choose TEST.
Under
Query Strings
use:💁♂ The id is irrelevant as this is only a mock.
Then select the Test button.
Example output:
Response Body (200)
Also scroll down to see the headers:
Response Headers
This is showing that we have set up
Access-Control-Allow-Origin
to be"*"
, so we can make simple AJAX calls to this resource from a different sub-domain.One down. Two more to go.
Now for the ratings one. Choose the GET method under
get_av_star_rating
. Choose TEST. For Query Strings just like before use:Then select the Test button.
You should get this back:
Response Body (200)
Response Headers
Again showing that this resource is accessible from simple AJAX requests from anywhere.
Perfect, you are on the home stretch. Let's test the last one for the creating report functionally.
Choose the POST method under
create_report
. We will leave the body empty.Choose Test.
You should get this:
Response Body (200)
Response Headers
📓 We have this set
Access-Control-Allow-Origin
to*
for now (essentially a placeholder). However we are not going to be using simple requests for this particular route. Later in this Lab we will be implementing OPTIONS with non-simple requests, which will lock this down more. It is fine for now though.Magic. It's all working, albeit, its using MOCK data. Our POST route is not using our OPTIONS preflight stuff yet.
Let's deploy this API and test it on the website.
Choose the root path
/
under Resources. Choose Actions and Deploy API. Under Deployment stage choose[New Stage]
. For Stage name paste intest
. Choose Deploy. Copy down the Invoke URL.Example endpoint (yours will be different)
Before we can test this on the website, we need update the API URL from null to that ^ actual API endpoint.
Follow these steps to update the website's config file:
Go back to the Cloud9 tab. In the
resources/website
folder in Cloud9. Update theresources/website/config.js
file with the newly created (and deployed) endpoint and save the file.Example:
📓 Note there is no trailing end slash there.
Run the
resources/setup2.sh
script to upload the newconfig.js
file.⚠️ If you are using Java. You will need to change directories to be in the
/home/ec2-user/environment/java8
directory before running the following commands.Should give you something like this:
Try visiting your API GW endpoint directly in the browser:
Note there is no route (pathname) mentioned within that raw endpoint. So if try to hit that URL in the browser we will get this.
Now try this with one of the GET routes using a querystring like so:
Example endpoint (yours will be different, swap out the subdomain with your bucket name like before)
You should get this. Proving your API is publicly accessible. #win
Time to see this working on the website. Head over to your website, who's config you have just updated.
If you don't have your URL in hand. You can type this in the Cloud9
CMD_LINE
to get it.Example:
If you search for an item on the website, and press "ratings" or "reviews" you should get data being returned.
If you try and use the
create_report
button it will tell you that you are not logged in. Which is fine for now, as we have not set that up yet.💁♂ Hence this is why that "login to admin" hyperlink on the website also points to nowhere right now.
Stage 3 - Setting up CORS for your POST route
Time to update your POST route, so that once we have authentication ready (next lab). This way the website can actually communicate securely with our API.
The way we can ensure this is to bypass the simple POST request and ask the browser to send a pre-flight request (OPTIONS) before sending the actual request with credentials.
The server (in this case API GW) needs to respond with which domain(s) is/are allowed to make the request, and if it is safe to send credentials or not.
In your respective folder in Cloud 9 there is a file called cors
. You should look at that and understand what is is doing for this POST API
⚠️ If you are using Java the folder structure for java is different from for Node.js or Python. You'll need to navigate to the parent folder for the program to run. The parent folder name will correspond with the file name for the other languages. In this case, the file is named cors
for node and Python, therefore the folder you should navigate to in the java folder is the cors
folder. Under that folder you should see a pom.xml
file - that is how you know you are in the right spot :)
You will see a method called updateIntegrationCORS
. This is where most of the magic is happening.
Essentially when a browser sends its pre-flight OPTIONS AJAX request we want to check its ORIGIN domain and send back a BIG GREEN OK. Only then, does the browser know that its ok to send the REAL POST request.
Run the cors
file as per the table below. This will update your POST API and ensure it is CORS powered, and ready for integration with your Authentication system (coming soon).
💁♂ If you are not in the right right folder in the CMD_LINE
. Navigate to it now.
For example if you are using Python use cd python_3.6.8
The following table shows the respective run command needed to run the cors
file:
Language
Filename You Need To Edit
Command to run via CMD_LINE
Node.js (v10)
cors.js
node cors.js
Python (v3)
cors.py
python3 cors.py
Java
App.java
mvn clean install && mvn exec:java -Dexec.mainClass=com.mycompany.app.App
Once you run the file in the CMD_LINE
you should see (regardless of language) the word done.
⚠️ If you are using Java, and you are seeing any compilation errors. Run the following command and try running the program again.
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.252.b09-2.51.amzn1.x86_64
Just to wrap up today, please take a few moments to navigate around the API GW console, and see how the method and integration settings from both script have been applied. Get comfortable navigating around that console.
Try testing the OPTIONS API.
Choose
/create_report
and then OPTIONS. Then choose TEST. Then Test again.You should see this in the body
no data
, and you should see the headers similar to the following:This is better now. It means that non-simple AJAX requests across domains to this POST request will encounter this during preflight. Essentially telling the browser it is OK to send the POST with credentials but only from your website's origin.
Awesome! You have your Kiosks communicating with the backend and retuning hard coded data, and you have future proofed your POST API ready for integration with Cognito.
Tomorrow (in the next lab). You are going to be setting up all that Authentication stuff with Cognito. Once you have that in place, then you can test the create_report
route.
A good day, today, you've done well. Get a good nights sleep as tomorrow things get a lot more involved <evil laugh>
😈
Last updated
Was this helpful?