This article is part of #ServerlessSeptember. You'll find other helpful articles, detailed tutorials, and videos in this all-things-Serverless content collection. New articles from community members and cloud advocates are published every week from Monday to Thursday through September.
Find out more about how Microsoft Azure enables your Serverless functions at https://docs.microsoft.com/azure/azure-functions/.
Introduction
The idea for this article is from the cloud resume challenge. We need to build a serverless static resume website with a visitor counter. We need a serverless service to store the visitor’s count (Azure Cosmos DB), a serverless service to retrieve and update the visitor’s count from our store(Azure Functions), a serverless service to host our static resume website (Azure Storage) and an additional service to cache and make our static website load faster (Azure CDN). This tutorial would be divided into four parts covering each steps and services
Building our store using Cosmos DB
Azure Cosmos DB is a fully managed NoSQL database service which is a perfect choice for our serverless store. Lets get started
Steps
- From azure portal, search for
azure cosmos db
and select the match - On the cosmos db page, select
create
- For Project details, choose your preferred Azure subscription and resource group to group your Cosmos DB account. For instance details, enter an account name of your choice which has to be globally unique, Our API would be
Core(SQL)
as we would be using SQL syntax, Capacity mode isserverless
and we can leave the remaining options to default and go ahead to selectreview + create
- Once deployment is complete, Select
Go To Resource
and chooseData Explorer
. On data explorer page, selectNew Container
. Enter adatabase id
,container id
, andpartition key
of your choice.
- After creating DB, select your created DB from the
SQL API
list and go ahead to selectNew Item
. Enterid
ashome
or whatever you would like to call your resume home page andcount
as Zero0
. Clicksave
and our store is ready for use.
Building our serverless function using Azure Function
Azure Function is a serverless compute service that lets you run event-triggered code without having to explicitly provision or manage infrastructure which makes it a great choice for our use case.
Steps
- From azure portal, search for
Function App
and select the match - On the function App Page, select
create function
- For Project details, choose your preferred Azure subscription and resource group to group your Function App. For Instance Details, Enter a function App Name of your choice which is globally unique. Select
Code
as option for Publish, SelectNode.js
as Runtime stack, Leave the remaining options as default and selectReview + Create
.
- Once deployment is complete, Select
Go to Resource
and selectfunctions
on the Resource page. - Select Add, and select
HTTP trigger
from the New Function popup. Leave the details option as default and SelectCreate Function
. - We would like update the visitor count table and get the updated count all from our Function. This is possible with Integration. Select
Integration
from the function page.
- Select
Add Input
to add an integration to get our visitors count for a specific page. Binding Type isAzure Cosmos DB
, Database name should be the name of our CosmosDB and Collection name should be the name of our Cosmos DB container both created earlier. Create a new Cosmos DB account connection using your created cosmos db account. Add an SQL query to get a specific page countSELECT * FROM c WHERE c.id = {id}
. This query selects an item from our cosmos db whereitem.id
is equal to our input query id. SelectOk
to create our input integration.
- Select
Add Output
to add an integration to update our visitors count for a specific page. Binding Type isAzure Cosmos DB
, Database name should be the name of our CosmosDB created earlier and Collection name should be the name of our Cosmos DB container. SelectOk
to create our input integration.
- Select
Code + Test
and your function should look something like this:
module.exports = async function (context, req, data) {
context.bindings.outputDocument = data[0];
context.bindings.outputDocument.count += 1;
context.res = {
body: data[0].count
};
}
The third parameter data
in our async function returns item from our cosmos db by running the SQL Query in the input integration we created earlier. An alternative to that would be
data = context.bindings.inputDocument
where inputDocument
is the name of the input integration.
To update the visitor count in our db, we get a reference to the item we want to update using the inputDocument binding and update the count by one before returning the result. Azure function is so smart that our changes are reflected on the returned data.
- Let’s test that our function works by using the
test/run
feature. We would normally make a get request to our endpoint and query parameter ofid
with a value ofhome
. We used a value of home since the item we want to get from our cosmos db was saved with anid
ofhome
. You should copy your Function App API endpoint so you can call it from your resume web page.
Hosting our static resume on Azure storage
I would assume we all can build a simple resume using html. You can build using any frontend framework but I used plain html, css and Javascript for mine. I won’t be going into the details of building the resume so feel free to clone mine here. The important thing you need to understand here is you would have to fetch the visitor’s count using Javascript from our Function App API endpoint and display the result on the web page. Let’s go ahead to upload our resume on Azure storage.
Steps
- From azure portal, search for
storage accounts
and select the match - On the storage accounts page, Select
add
. - For Project details, choose your preferred Azure subscription and resource group to group your Function App. For Instance Details, Enter a storage account Name of your choice which is globally unique. Leave the remaining options as default and select
Review + Create
. - Once deployment is complete, Select
Go to Resource
.
- Select
Static website
, on static website page, selectenable
as it's disabled by default. Enter your resume website index page and error page and clicksave
. You can see the url to your static website but it’s empty since we haven’t uploaded our files. Select the$web
container to upload your files.
- Upload your files and make sure your Javascript uses the Function App api gateway to retrieve the visitor’s count.
- We need to update our function App to allow request from our static website url else we wouldn’t be able to get the visitors count. go to the Function App you created and search for
CORS
. add your static website url to list of allowed origins. Make sure to enableAccess-Control-Allow-Credentials
. Everything should work fine now.
Using Azure CDN to cache resume and reduce load times
Azure Content Delivery Network (CDN) lets you reduce load times, save bandwidth, and speed responsiveness.
Steps
- Go to storage accounts and select the storage for your static website.
- search for CDN and select
create new CDN endpoint
- Choose
create new
, enter a name for your CDN profile. Select theStandard Microsoft
option for pricing tier. Enter a globally unique name for CDN endpoint name and select the storage account as origin name. clickcreate
and wait for some minutes while it deploys your content to CDN. Don't forget to add your CDN endpoint url to list of allowed origins in your Function App.
Here's our final result.
Conclusion
We have successfully hosted our resume on azure storage and used Azure CDN for caching, Azure Cosmos DB to store visitor's count and Function App to retrieve the count. An added functionality on your own would be to add a custom domain to our CDN integration.
Top comments (4)
Thanks for the guide, it helped me a great deal.
For those getting the HTTP 500 internal server error:
It is probably because of the connection bindings. There's a bug in Azure Functions where it creates the bindings with v3 code instead of v4 (which is what it runs the code with hence the errors). Bug report here
This is what the code looks like:
This is what it should be (notice containerName and connection attribute):
Once I fixed this it gave me a different error: "Format of the initialization string does not conform to specification starting at index 0."
To fix this one you need to manually add the correct connection string under your Function App's Environment variables. My two connection strings were incorrect for some reason.
Nobody follow this. The challenge asks to use PYTHON. For some reason this guy chose node.js and more JS. Which the code he uses doesn't even work. Produces HTTP 500 internal server error.
HTTP response code
500 Internal Server Error
HTTP response content
Do you have any link or study material for python visitor count instead of js. I am also trying this project.
I am receiving this after trying to test:
HTTP response code
500 Internal Server Error
HTTP response content
Do you know why that is?
Some comments have been hidden by the post's author - find out more