Implement middleware pattern in Azure Functions

Emanuel Casco
Jan 4, 2019 · 3 min read

How to implement middleware pattern in Azure Functions to keep our functions clean.

Image for post
Image for post
Movement — Ph: Burak K

Also available in spanish.

Introduction

I wrote this post to share my experience implementing middleware pattern in Azure Functions.

Azure Functions is a serverless compute service that enables you to run code on-demand without having to explicitly manage infrastructure.

Biggest advantage of serverless computing is that you can focus on building apps and don’t worry about provisioning or maintaining servers. You can write code only for what truly matters to your business.

But in real world applications you have to deal with some common technical concerns outside business logic, like input parsing and validation, output serialization, error handling, and more.

Very often, all this necessary code ends up polluting the pure business logic code in your functions, making the code harder to read and to maintain.

Web frameworks, like Express, Fastify or Hapi, has solved this problem using the middleware pattern. This pattern allows developers to isolate these common technical concerns into “steps” that decorate the main business logic code.

Implementation

After deciding to implement this pattern in my project, I made a small search to check if someone had already implemented a similar solution.

Unfortunately, the few solutions I found didn‘t meet my needs, so I decided to implement it myself.

That’s is how Azure-Middleware was born.

How it works

Validation

In serverless arquitectures is essential to be able to determine the correct behavior of each function as separate pieces of code. Therefore, in order to avoid unexpected behaviors, is important ensure that function inputs belong to its domain.

To accomplish this mission Azure-Middleware uses Joi. It allows us to define a schema and check if the input message is valid or not.

With the validate method you can define the scheme that will be used to validate the messages. If your function is called with an invalid message then an exception will be thrown and your function won’t be executed.

module.exports = new MiddlewareHandler()
.validate(invalidJoiSchema)
.use(functionHandler)
.catch(errorHandler)
.listen();

Function chaining

use method is used to chain different function handlers, or middlewares, as “steps”. It expect a function handler as argument.

Each middleware is executed sequentially in the order in which the function was defined. Information flow passes to the next element of the chain when calling context.next.

module.exports = new MiddlewareHandler()
.validate(schema)
.use((ctx, msg) => {
ctx.log.info('Print first');
ctx.next();
})
.use((ctx, msg) => {
ctx.log.info('Print second');
ctx.done();
})
.catch(errorHandler)
.listen();

next is a method injected into context. It is used to iterate the middlewares chain.

Error handling

Error handling is very similar as it works in web frameworks like Express. When an exception is thrown, the first error handler into the middlewares chain will be executed. While all function handlers before will be ignored.

Also, you can jump to the next error handler using next. If this method receives an argument as first argument then it will be handled as an error.

Also, you can jump to the next error handler using context.next. If this method receives a non-nil value as first argument, it will be handled as an error.

Unlike the function handlers, the error handlers receive an error as the first argument.

module.exports = new MiddlewareHandler()
.use((ctx, msg) => {
ctx.log.info('Hello world');
ctx.next('ERROR!');
})
.use((ctx, msg) => {
ctx.log.info('Not executed :(');
ctx.next();
})
.catch((error, ctx, msg) => {
ctx.log.info(errors); // ERROR!
ctx.next();
})
.listen();

Wrap up

The package is still in development and I have some ideas to improve it. However, if you have any suggestion, please don’t doubt in contact me and let me know about it!

Thanks for reading. If you have thoughts on this, be sure to leave a comment.

You can follow me on Twitter, Github or LinkedIn.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store