Azure Functions for Static Web Apps

Azure functions for Static Web Apps
Table of Contents

Use Azure Static Web Apps to add Azure Functions that provide a website API. Create these APIs using Azure Static Web Apps, Visual Code and GitHub. 

Azure Functions are available in a variety of languages and have a support community. Today we will show you how to add an API using an Azure Function, written in Typescript, to a vanilla HTML page. The Azure Function saves the data to Azure Table Storage.

Setup

 We assume that there is an Azure Static Web App configured as described in the previous post and we will expand on that. If we have all the previous prerequisites, we will need two additional items, the Azure Static Web Apps Extension for Visual Studio Code and an Azure Storage Account.

Web page

This solution does not use a schema for the data and uses a standard web form. This means we can use whatever fields we like. We are going to POST the data to the function. The essential bits are:

<form id="form" action="/api/processForm" method="POST"> 
<div> 
<!-- your form fields here → 
<button type="submit" class="myButton">Contact Me</button> </div> 
</form>

We specified a basic event listener for the submission:

<script> 
document.addEventListener("submit", function (event) { event.preventDefault(); 
const form = event.target; fetch(form.action, { 
method: form.method, 
body: new FormData(form), }) 
.then(function (response) { 
if (response.ok) { 
form.reset(); } }) 
.catch(function (error) { 
console.warn(error); 
}); 
}); 
</script>

Resetting the form shows success.

Azure storage account

Creating an Azure Storage Account is very simple just log onto the Azure portal and Create Storage Account. For good housekeeping, use the same Resource group and Region as the base Web App. 

Azure Storage Account

Now that we have a storage account we can create a table, called ‘Request’, for our App to use:

Azure table

While you are in Azure, on the Storage account tab, go to Security + Networking > Access and ‘Show keys’. Take a copy of a Connection string. You can put this into local.settings.json:

Azure connection string

Azure function

The Azure Web App Extension to Visual Studio Code will create a default  Azure Function and all the files and folders.

Press F1 to open the Command Palette.

Select Azure Static Web Apps: Create HTTP Function…

Azure http function

We select Typescript as our language:

Azure TypeScript

This is what the default function looks like:

import { AzureFunction, Context, HttpRequest } from "@azure/functions" const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> { context.log('HTTP trigger function processed a request.'); const name = (req.query.name || (req.body && req.body.name)); const responseMessage = name ? "Hello, " + name + ". This HTTP triggered function executed successfully." : "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."; context.res = { // status: 200, /* Defaults to 200 */ body: responseMessage }; }; export default httpTrigger;

We are going to replace it with this:

import { AzureFunction, Context, HttpRequest } from "@azure/functions" import { Guid } from "guid-typescript"; import {createTableService,} from "azure-storage"; import parseMultipartFormData from "@anzp/azure-function-multipart"; interface key { PartitionKey: string; RowKey: string; } const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> { context.log('HTTP trigger function processed a request.'); const tableService = createTableService(); const thisKey : key = {PartitionKey: "Test", RowKey: Guid.create().toString()}; const { fields } = await parseMultipartFormData(req); const params = fields.reduce((obj, item) => Object.assign(obj, { [item.fieldname]: item.value }), {}); const entity = {...thisKey,...params}; const tableName = "Request"; tableService.insertEntity(tableName,entity,{ echoContent: true }, function (error, result, response) { if (!error) { context.res.status(200).json(response); } else { context.res.status(500).json({ error: error }); } }); }; export default httpTrigger;

This function is quite minimal, but it achieves its purpose, which is to insert the contents of the request into the table using the table service. This is familiar territory to any node and npm user, the packages need to be installed, then it is ready for testing.

The POST cannot give us data in the required object format so we use the parseMultipartFormData function to create an array which we reduce to an object with properties that correspond to the form fields and pass that along with a key to the table service. This enables us to have a generic function that will pass all the fields of the form to the table with no requirement for a schema.

Debugging

Getting an Azure function to do what you require may require some debugging, fortunately this is easy to achieve.

Select the Azure Function in Visual Code and hit F5, this will create a debug session:

Functions:

processForm: [GET,POST] http://localhost:7071/api/processForm

Then select another terminal session and type:

swa start . --api=http://localhost:7071

Now you can debug the function which is an essential for this type of work.

Azure Storage Explorer is a free tool that enables us to manage our Azure cloud storage resources from the desktop, in a very convenient package.

View your inserted data using the Azure Storage Explorer:

Azure storage explorer

Deployment

We have used the Azure Static Web Apps project we created we created in the previous post. Deploy the Web Page and Function by committing the changes to Git and pushing to GitHub. We need to update the workflow to deploy the function. Edit the GitHub workflow yaml. Search for the property api_location and set the value to “api”.

api_location: "api" # Api source code path - optional

Then we just need to add the  AZURE_STORAGE_CONNECTION_STRING to Settings > Configuration , save it, and it should be good to go.

If your configurations are not correct, you may find a 405 or 500 error returned. Use the Azure web interface to check your deployment, see something like this:

Azure web interface

Conclusion

We have shown how to extend this Static Web App with serverless APIs powered by Azure Functions to encapsulate compute requirements via reusable API endpoints with dynamic scale based on demand. Azure Static Web Apps are a useful addition to the web workers toolkit. Azure Functions extend this capability and provide some exciting possibilities. The key takeaway is that Azure Functions are a quick and relatively simple way of adding API functionality to an Azure Static Web Apps website.

Recent resources

What is LDAP Injection? Types, Examples and How to Prevent It

Learn what LDAP Injection is, its types, examples, and how to prevent it. Secure your applications against LDAP attacks.

Read more

How to Use Dependency Injection in Java: Tutorial with Examples

Learn how to use Dependency Injection in Java with this comprehensive tutorial. Discover its benefits, types, and practical examples.

Read more

Idempotency: The Microservices Architect’s Shield Against Chaos

Discover the power of idempotency in microservices architecture. Learn how to maintain data consistency and predictability.

Read more