Lets do coding on AWS
Previously on Compsortia learning …. building a static website. (ahem – page) on AWS. It was awesome as we got to learn and play with Route 53 and S3 buckets. But now – it gets real, well a little more real as we look at build – wait for it – a dynamic web page – oh yeah – we’re going to be billionaires.
So how do we do that with AWS and what is a dynamic web page. Well we’ll start building in a second but to confirm a dynamic webpage is a page that takes in an input from somewhere, does something to it and either returns something related to that input or just stores for analysis somewhere else or gives a response depending on something the computer already knows like the time of day. Cool. For this project we simply take something in and give something back. Let’s go people!
Here’s the plan. As a visitor to enter a number and then we will … double it. How useful is that. We do have to do a bit of boring design and planning, urgh, but go to have a rough idea of direction and clothing before setting off.
So. We need
- a webpage which is accessible to the public
- Someway of taking in a number
- Someway of doubling that number
- Someway of displaying the doubled number
going Dynamic – Amplify
In the first project we built a static webpage and at the time AWS did say that we should use Amplify to do webpages and that is what we are going today. AWS Amplify is a super cool tool to help connect all the components of a dynamic website without as much faff as normal. Now a dynamic website has the components we talked about earlier: user interface (webpage), some thing that changes on the page or something taken in on the page, and 9 times out of 10 a way of storing information given or retrieved via a data storage thing like a database. Amplify helps to connect all those things together.
The first thing we need to do is create a simple webpage that will eventually hold our snazzy double number page. A simple webpage has two parts: head and body. The head of a html page can contain things that change the page but are not visible. So we can use a style sheet to format and colour the page and we can add scripts to make the page more interactive like when you click a button. So let’s add the script thing at the top as we’ll be coming back to that part. There is no formatting so the page will be very basic but we can do the colouring in another time. So our page looks like this:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Compsortia - AWS Project 2 - Dynamic Webpage</title>
<script></script>
</head>
<body>
<h1>Double Your Number</h1>
<p>Enter a number and we will double it for free</p>
</body>
</html>
Save this as index.html and this is where it gets a different. In project 1 with the static page and the S3 buckets we uploaded the file into the bucket and pointed things at it. With Amplify it’s different. We need to change the file into a compressed format commonly a zip file from the old days of moving big and lots of files onto a Zip disk and then loaded onto another computer like you would put clothes in a bag and then zip up the bag which would squash or compress them (changing a load of files from one format to another that can be reversed is also a security thing but that’s not relevant for today. The reason Amplify uses this method is to provide a method of uploading a lot of documents in a single bundle which it can unpack and structure. So you could upload a whole website in one go. This is handy as you could have a development environment to play in, a test environment and then a production environment so you could upload to each site when ready. For now it’s just one file which we will save as index.zip.
Search for Amplify in AWS and once you have found it it will show you the apps you have deployed. Should be blank but either way click ‘Create new app’. Amplify presents a 4 step process to getting an app live. Select the Deploy without Git as we don’t have a code store or repository or ‘repo’ but when we get fancy we’ll do this to manage how we make changes over multiple files made by multiple people.
Super. Next name the App – we’ll call in DoubleName and leave everything else the same. Then drag the index.zip over or click the the Choose .zip folder and upload the index.zip file. When successful it will say ‘Uploaded’. Then click Save and deploy.
Amplify will then take a more to ‘deploy the app’. This sounds scary and fancy and it is. Amplify has done a tonne of stuff in the background to get that simple page ready. You will then be offered the three other steps but ignore them and click ‘Visit deployed URL’. This will bring you to the link at the bottom of the page something like https://staging.d176hehqtdvfiv.amplifyapp.com. If everything has gone as planned you will see a super simple page with a title
Double your Number
Enter a number and we will double it for free
Nice! Another static page on AWS. All we need to do now is and an About Us and a Contact Us and it will feel like 1998 all over again (great days). But we are just getting to the start of things. Let’s go dynamic and to do this lets talk serverless code and Function as a Service (FaaS) and … sorry – got carried away there.
We do need to add a way of making the page interactive. There are many way to do this with a common way having a client (like the an Internet browser) send data to a server and the server processes the data as it was designed to do. This client-server model is awesome but there is one draw back to it that cloud computing can deal with and that is having a computer sitting there doing nothing until asked. What if you could spin up a server and then spin it down again? What if you could spin up just the tiny slice of the server to just run the query being asked? Well you can – you can create a thing to process input called a function and have it only existing when called for. Let’s demonstrate (remember we have already bagged the static webpage)
Lambda – getting dynamic
Now, this gets more complicated but we are going to go through it first with no code so you can see how it all works and then we will go back and put the code in so you know the difference between the default bits and the bit.
Our first function. Go to Lambda and you’ll get the landing page. Select Functions on the left hand side. This will show all the functions for that account and that region.
Click create function. Select Author from scratch and name the function DoubleNumber. For Runtime pick Python 3.13 and then ‘Create function’. Hooray – our first function.
Cool. You should see the DoubleFunction function. If not select from the left hand side. With the function selected you will see me have a function overview and below that a load of tabs. Below that the Code source. This is what the default python code looks like
import json
def lambda_handler(event, context):
# TODO implement
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!')
}
Let’s break this down. First we have import JSON. This a set of instructions or a library that python needs to use JSON which is format of the data that will be taken in, processed and given out.
Next def lambda_handles(event, context): This is the first line of the function called lambda_handler which can take in two variables called event and context. We’ll cover each when we do the coding.
Next is a comment line #TODO implements that tells you were to put your actual code (we’ll get to that later as well).
Lastly
return {
‘statusCode’: 200,
‘body’: json.dumps(‘Hello from Lambda!’)
}
This defines what the user will be returned if the code is successful. The statusCode 200 is the server telling the client that everything is good. body: json.dumps is a function from the json library we imported at the top. “dumps” means write ‘Hello from Lambda to the variable body which will be in the pop up windows when the user presses the “double” button which we will create. You’ll see this all working when we have it all set up.
Okey dokey. One default function which we haven’t changed but when we do it will be under the function section.
Right. We have a function that will return some simple text and a webpage. Now we have to connect the two and we do with the API Gateway which means we will connect the page to the function through something called an application programming interface (API). Think of an API like a menu where the client can ask for things from the menu which are then returned e.g. ice_cream:”strawberry”, cone:”chocolate”.
Find API Gateway a click Create API. We can choose between 4 APIs which are really only 2 types: API and WebSocket. Don’t worry about this for now. We want to choose the REST API – click build.
Cool. Now name the API DoubleNumber_API and then click Create API. We have our first API. But an API needs away to communicate the data it takes in to the place that uses the data. We need a method. Click Create method. You’ll be shown page where you need to select a method type. On our page the user will be sending data to the lambda function so we chose the POST method as we are posting data to a service. There are other methods but just pick POST for now. Then pick Lambda function and the function we created earlier, DoubleFunction, that is just the default details. Click create method and now we are really cooking.
Select the POST method we just created and you will see a picture flow of how it works. Under this there are a bunch of tabs for that method. We want the last one – Test. As we left the lambda function with no changes there are no test parameters for us to add. So click Test. We will get back what happens when the API is called – we get a same response that is the in function.
{"statusCode": 200, "body": "\"Hello from Lambda!\""}
Excellent this is now working. So we have a webpage, an API connected to a lambda function. We’re not quiet done as to connect the gateway to the API or to send data to it (even though we are not) as the moment we have to enable CORS by pressing the button Enable CORS. CORS stands for Cross-origin resource sharing which simply means resources like lambda functions, S3 buckets, databases can talk to each other as they are stored in different areas of the account. Tick the POST option under Access-Control-Allow-Methods and then click save.
Super we are nearly there. The last step is to deploy the API so it can be used. Go back to the DoubleNumber_API and you should see a button labelled Deploy API. Click that and you’ll get a window asking for a stage. Choose New stage and label that ‘dev’. Great job. The stage will have an invoke URL in this case https://o4ixt0ozxk.execute-api.eu-west-2.amazonaws.com/dev. Copy your version down as we will need it in the final part – running the code.
So recap. Webpage -> API -> Gateway -> Function -> Gateway -> API -> Webpage
The problem now if there is nothing on the web page for us to trigger the sending of information to the API and down the line. We need to change the page to make it interactive – like a button. And if you want to put a button on a web page we need to use javascript.
Now, don’t panic if you’re thinking we’re breaking out all the computer science shnizzle but we are going to have to walk through a few basics and how it works. Nice and slow.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>To the Power of Math!</title>
<!-- Styling for the client UI -->
<style>
h1 {
color: #FFFFFF;
font-family: system-ui;
margin-left: 20px;
}
body {
background-color: #222629;
}
label {
color: #86C232;
font-family: system-ui;
font-size: 20px;
margin-left: 20px;
margin-top: 20px;
}
button {
background-color: #86C232;
border-color: #86C232;
color: #FFFFFF;
font-family: system-ui;
font-size: 20px;
font-weight: bold;
margin-left: 30px;
margin-top: 20px;
width: 140px;
}
input {
color: #222629;
font-family: system-ui;
font-size: 20px;
margin-left: 10px;
margin-top: 20px;
width: 100px;
}
</style>
<script>
// callAPI function that takes the base and exponent numbers as parameters
var callAPI = (base,exponent)=>{
// instantiate a headers object
var myHeaders = new Headers();
// add content type header to object
myHeaders.append("Content-Type", "application/json");
// using built in JSON utility package turn object to string and store in a variable
var raw = JSON.stringify({"base":base,"exponent":exponent});
// create a JSON object with parameters for API call and store in a variable
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
// make API call with parameters and use promises to get response
fetch("YOUR API GATEWAY ENDPOINT", requestOptions)
.then(response => response.text())
.then(result => alert(JSON.parse(result).body))
.catch(error => console.log('error', error));
}
</script>
</head>
<body>
<h1>TO THE POWER OF MATH!</h1>
<form>
<label>Base number:</label>
<input type="text" id="base">
<label>...to the power of:</label>
<input type="text" id="exponent">
<!-- set button onClick method to call function we defined passing input values as parameters -->
<button type="button" onclick="callAPI(document.getElementById('base').value,document.getElementById('exponent').value)">CALCULATE</button>
</form>
</body>
</html>
# import the JSON utility package
import json
# import the Python math library
import math
# define the handler function that the Lambda service will use an entry point
def lambda_handler(event, context):
# extract the two numbers from the Lambda service's event object
mathResult = math.pow(int(event['base']), int(event['exponent']))
# return a properly formatted JSON object
return {
'statusCode': 200,
'body': json.dumps('Your result is ' + str(mathResult))
}
