Skyler Hartle is on the Azure Functions team and focuses on APIs, growth hacking, and other neat things.
*record scratch*
*freeze frame*
Yup, that's me. You're probably wondering how a former JavaScript developer ended up using Azure Functions for all his API-related projects.
Before I joined Microsoft, I spent most of my days developing API-related applications using Node.js, or more specifically, I leveraged the MERN stack (MongoDB, Express, React, and Node) to create different applications, back when that was still the hotness.
Like many of us, I gravitated towards the simplicity provided by something like Node.js + Express together. It just worked. And it was fast to get started. Easy to spin up new projects and services as needed. As time progressed, I eventually gravitated towards the next shiny thing -- JAMstack (JavaScript, APIs, Markdown) -- because of a similar allure; discrete layers, speed, ease of use, and an appealing mental model for developing new applications that made sense to me.
The technologies involved all had a similar theme:
After I joined Microsoft (and subsequently joining the Azure Functions team), I discovered a spooky truth. Many, many people were using serverless platforms, like Azure Functions, for their API-related applications. It turns out that building APIs is one of the most popular use cases for Azure Functions-- for good reasons.
I immediately began investigating what this meant for somebody like myself, a developer with a strong passion for APIs and good API development and API design, and this is what I discovered along the way.
Why developing APIs with Azure Functions is a good great the best thing
The programming model for Azure Functions requires that you create small, single units of compute that are perfect for routes in an API. If you're coming from a background using other frameworks, such as ASP.NET, Django, Flask, Express, Koa, etc, you're already familiar with an application model that has an opinionated way of creating routes for your API. The jump from this mental model to using something like Azure Functions is not difficult and is more of an evolution of this existing way of doing things than a complete divergence.
If you aren't familiar with Azure Functions, here's a quick overview:
- Azure Functions is a "functions-as-a-service" platform, allowing you to run code in the cloud without managing servers.
- In Azure Functions, you create function apps.
- Inside a function app, you have a series of functions.
- Inside those functions, that's where your code lives.
- Thus, a function app is just a collection of functions, with each function containing a bit of code, and that's it!
Much in the same way that a framework such as Flask (for Python) or Express (for Node) might generate scaffolding code and files for you, Azure Functions just goes one step further by providing the scaffolding and the hosting environment to run your API.
Here's an example of how you might use Azure Functions to create an API:
- You create a function app (a grouping of multiple functions) called "UserAPI".
- Inside this function app, you create four functions, each of which responds to an HTTP request in a different way: GetUser, CreateUser, ModifyUser, DeleteUser.
- Write the business logic inside each individual function, corresponding to each specific route.
- A new URL is generated per function (not per function app!), that you can direct specific requests towards, such as GET, POST, PATCH, and DELETE requests. For example, a GET request may be directed towards GetUser, POST requests towards CreateUser, PATCH requests towards ModifyUser, and DELETE requests directed towards DeleteUser.
Each function is self-contained, allowing you to modify the business logic within the function, add additional dependencies to the function, without polluting the scope of the other routes, or introducing unnecessary complexity elsewhere in the global scope of your application.
The business logic for each function may differ, but the way you create a new function is the same.
The image below reflects the same function app structure as outlined in the numbered steps above.
To sum up why all of this is a good thing:
- A function is a discrete unit of compute, encapsulated and living within its own context. This allows you to pull in only the dependencies you need, for the exact logic you're trying to run.
- Spinning up a new function via VS Code is without a doubt the fastest way to create a new, external API, compared to other methods such as virtual machines.
- Azure Functions provides not only ready-made scaffolding for writing an API, but all the necessary hosting.
- Serverless models enable consumption-based pricing which means you pay nothing when there is no traffic hitting against your API.
- When there is massive traffic hitting your API, functions will automatically scale with respect to demand, ensuring no outages for this often critical layer of your application infrastructure.
The 'Hello, world' tutorial, HTTP endpoint style
If you want to test out Azure Functions for yourself, you can follow the very (overly) simple instructions below to try this for yourself, in only four steps. The simplified tutorial below will provision a new function app for you, with a single function, exposed to the world as an HTTP endpoint.
- Prerequisite: install the Azure Functions VS Code extension.
- Once installed, open the Azure Functions extension and click 'Create New Project', select a folder for your project.
- When prompted, select 'HTTP trigger' as your template and hit enter a few times (don't worry about those pesky details).
- Click 'Deploy to Function App’.
- Once the deployment has finished, you can browse into the resource group, find the function, and right click to copy the newly created function URL.
- Throw that thing into your favorite browser, and see the results!
'Create New Project' button, on the Azure Functions extension.
'Deploy to Function App' button, on the Azure Functions extension.
Find the URL for your newly deployed function.
The above example is just a quick intro, but it works! Your application can't do anything meaningful, but if you want to do more with the function app you just created, the structure is in place for you to add business logic to your API now with minimal effort.
If you want a more comprehensive tutorial, you can read our quickstarts to learn how to do this in a variety of different environments.
Generating a function app from OpenAPI specifications
Let's crank this sucker up to 11.
If you're already in-the-know with APIs, it's likely you're either using or at least familiar with OpenAPI specifications (Swagger). OpenAPI specifications are machine-readable documents that describe RESTful API services, which has a number of useful purposes.
There are two main schools of thoughts on when/how to use OpenAPI specifications:
- Code-first, where you develop an API, and then generate a file such as an OpenAPI specification, or...
- Design-first, where you write a document, such as an OpenAPI specification, that describes the intended functionality of the API.
More recently, design-first API development has been getting attention, especially when leveraging a descriptive document such as an OpenAPI specification. This document effectively becomes a contract; teams of people can develop against an agreed upon OpenAPI specification, knowing that this document reflects the truth of the API. An OpenAPI specification serves as the contract, documentation, and source of truth for the API, making it a great way to plan out an API for a service.
To support the design use case, we recently released an update to our Azure Functions VS Code extension that lets you generate a function app from an OpenAPI specification. This is a brand new feature (in preview), with support for TypeScript, Python, Java, and C#. JavaScript and PowerShell coming soon!
For developers familiar with something like Flask or Express, this functionality basically creates all of the scaffolding necessary to get started building an API, similar to how you might use one of the aforementioned frameworks. It goes beyond that, too, inferring important route information from your OpenAPI specification and automatically generating route-related details within your function for things like parameters. You can check out the GitHub repo for more documentation, or go through this simplified quickstart:
To check this out, all you need to do is:
- Prerequisite: Make sure you have the latest version of the Azure Functions VS Code extension installed.
- Prerequisite: You’ll also need the correct language runtimes installed for the type of function app you want to create.
- Prerequisite: Install AutoRest, which is used as a dependency by the plugin.
- Create a new function app and choose the 'HTTP trigger(s) from OpenAPI V2/V3 Specification'.
- Choose your language of choice (TypeScript, Python, C#, or Java).
- Select your OpenAPI specification, and boom! Magic starts to happen!
To see the magic happening, the following gif steps you through this process for a Python app, and shows the end result:
A complementary functionality is also (coming soon) in the Azure API Management VS Code extension, wherein you will be able to generate a function app from an existing API you are managing within API Management. If you’re interested in learning more about how you can explore Azure Functions and Azure API Management together, we recently published a new workshop on Serverless APIs on GitHub.
We also support the ability to do this from CLI commands, as well, as shown in the example below:
autorest --azure-functions-typescript
--input-file:C:\\path\\to\\spec.json
--output-folder:./generated-azfunctions
--version:3.0.6314
--no-namespace-folders:true
For more examples of this, refer back to the GitHub repository for this new feature.
Wrapping this thing up
For those of you who work extensively on API-related use cases and are considering making the switch, I highly recommend examining the value that something like Azure Functions can bring to your development process (and the improvements to your quality of life). I’m a paid shill for Azure Functions, so of course, take what I say with a grain of salt, but as a lifelong developer and lover of technology, I would never advocate for something I didn’t believe in.
Let us know how we can make Functions better for you. Tweet us @azurefunctions, or you can send me a message, @skylerhartle, on Twitter, if you want to chat.