DEV Community

Akande Bolaji
Akande Bolaji

Posted on

Creating a Serverless Resume with Visitor Counter in Azure

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

Alt Text

  • 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 is serverless and we can leave the remaining options to default and go ahead to select review + create

Alt Text

  • Once deployment is complete, Select Go To Resource and choose Data Explorer. On data explorer page, select New Container. Enter a database id, container id, and partition key of your choice.

Alt Text

  • After creating DB, select your created DB from the SQL API list and go ahead to select New Item. Enter id as home or whatever you would like to call your resume home page and count as Zero 0. Click save 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

Alt Text

  • 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, Select Node.js as Runtime stack, Leave the remaining options as default and select Review + Create.

Alt Text

  • Once deployment is complete, Select Go to Resource and select functions on the Resource page.
  • Select Add, and select HTTP trigger from the New Function popup. Leave the details option as default and Select Create 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.

Alt Text

  • Select Add Input to add an integration to get our visitors count for a specific page. Binding Type is Azure 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 count SELECT * FROM c WHERE c.id = {id}. This query selects an item from our cosmos db where item.id is equal to our input query id. Select Ok to create our input integration.

Alt Text

  • Select Add Output to add an integration to update our visitors count for a specific page. Binding Type is Azure 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. Select Ok to create our input integration.

Alt Text

  • 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
  };
}

Enter fullscreen mode Exit fullscreen mode

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.

Alt Text

  • 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 of id with a value of home. We used a value of home since the item we want to get from our cosmos db was saved with an id of home. 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.

Alt Text

  • Select Static website, on static website page, select enable as it's disabled by default. Enter your resume website index page and error page and click save. 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.

Alt Text

  • Upload your files and make sure your Javascript uses the Function App api gateway to retrieve the visitor’s count.

Alt Text

  • 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 enable Access-Control-Allow-Credentials. Everything should work fine now.

Alt Text

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

Alt Text

  • Choose create new, enter a name for your CDN profile. Select the Standard Microsoft option for pricing tier. Enter a globally unique name for CDN endpoint name and select the storage account as origin name. click create 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.

Alt Text

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)

Collapse
 
servt0306 profile image
Servt0306

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:

    {
      "name": "outputDocument",
      "direction": "out",
      "type": "cosmosDB",
      "connectionStringSetting": "afreen-cosmosdb_DOCUMENTDB",
      "databaseName": "outDatabase",
      "collectionName": "MyCollection",
      "createIfNotExists": true,
      "partitionKey": "/id"
    }
Enter fullscreen mode Exit fullscreen mode

This is what it should be (notice containerName and connection attribute):

    {
      "name": "outputDocument",
      "direction": "out",
      "type": "cosmosDB",
      "connection": "afreen-cosmosdb_DOCUMENTDB",
      "databaseName": "outDatabase",
      "containerName": "MyCollection",
      "createIfNotExists": true,
      "partitionKey": "/id"
    }
Enter fullscreen mode Exit fullscreen mode

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.

Collapse
 
depa1m3r profile image
Info Comment hidden by post author - thread only accessible via permalink
Ian

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

Collapse
 
guru_quebec profile image
Guru Quebec

Do you have any link or study material for python visitor count instead of js. I am also trying this project.

Collapse
 
derek_edwards_e6343483988 profile image
Derek Edwards

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