npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

azure-functions-middlewares

v1.1.0

Published

The most complete middleware solution for ⚡ Azure Functions.

Downloads

750

Readme

Azure Functions Middlewares is a full HTTP middleware cascade solution if you need to evolute your Azure Functions to composition and reusability, as you did before on APIs powered by Express, Koa or HAPI.

See all features.

Table of contents


Installation

Requirements

Azure Functions Middlewares was tested for the environments below. Even we believe it may works in older versions or other platforms, it is not intended to.

| Environment | Tested version | | ------------------- | ------------------- | | OS | Ubuntu 20.04 | | Node.js | 12.16.3 | | Package Manager | npm 6.14.5 | | Platforms | server, browser not supported |

Installing

Via package manager

$ npm install --save azure-functions-middlewares

Usage

TL;DR

The most simple usage

const FunctionMiddlewares = require('azure-functions-middlewares');

const app = new FunctionMiddlewares();

app.use(async (context) => {

});

module.exports = app.listen();

⚠ Things you must pay attention

  • Always call listen() at the end of cascade to return the function entrypoint.
  • Always use async functions as middlewares. This project doesn't supports sync functions anymore, we are at 21th century.
  • Do not return anything inside your middleware function, unless you want to throw an error. Always use context.res to output what you need. If you want to pass values to the next middlewares, use the context object reference.

Capturing errors

If the middleware cascade encounters an error thrown by any middleware, it will stop the execution and will call the middleware registered with catch() method.

You can register a callback middleware to catch errors thrown in middleware cascade by passing a synchronous function with the arguments (context, error) , e.g.:

app.catch((context, error) => {
  context.res.status = 404;
  context.res.headers['X-Message'] = error;
});

If you don't register any catch middleware, a default function will be registered to log the error using context.error() and also to set a HTTP 500 status code.


Customizing the execution order

The middleware cascade is executed in three different phases: pre-execution, main execution and post-execution.

By default, all middlewares are pushed to the main execution phase, but you can customize the phase you are adding a middleware by passing a phase argument when registering a middleware using use() or useIf():

app.use((context) => {
  context.log('This will be executed at the last phase');
}, app.Phases.POST_PROCESSING);

app.use((context) => {
  context.log('This will be executed at the first phase');
}, app.Phases.PRE_PROCESSING);

app.use((context) => {
  context.log('This will be executed at the second phase');
});

Phases constants to use as phase argument are exposed into cascade's property Phases:

app.Phases.PRE_PROCESSING // => first phase
app.Phases.MAIN // => second phase
app.Phases.POST_PROCESSING // => last phase

These constant values are equal to its enums keys. So, the PRE_PROCESSING constant is equal to a "PRE_PROCESSING" string.


Conditional middlewares

You can conditionally using the method useIf() instead the traditional use() method.

To specify the evaluation function, pass to the first argument a synchronous function (context) => {} that always returns a boolean value.

Example:

const isPostRequest = (context) => context.req.method === 'POST';

app.useIf(isPostRequest, (context) => {
  context.log('This will be executed only if is a HTTP POST');
});

Stoping the cascade execution

You can stop the cascade execution and prevent next middlewares to be executed in any middleware, by returning the STOP_SIGNAL in the middleware.

It is useful when a middleware is used to validate the request before return any resource, just like Content-Type negotiation, authorization, etc.

The STOP_SIGNAL constant is avaiable as the second middleware's argument.

Example:

app.use((context, STOP_SIGNAL) => {
  if (!req.query.access_token) {
    context.res.status = 401;

    return STOP_SIGNAL;
  }
});

The STOP_SIGNAL constant value are equal to a "!STOP!" string.


Accessing and modifying the context

The context argument avaiable in middlewares is the untouched reference to the Azure Function Context object.

This means you can access the request using context.req property, and also set the response using context.res property.

By default, context.res and context.res.headers are always initialized with empty objects {} to prevent attributions to undefined.

The context argument is an object reference and added properties are avaiable through other references.

This means you can add your own custom properties to make them available to other middlewares.

For example, you could make an "User" property available to use user's information:

app.use(async (context) => {
  context.user = await database.getUser(context.req.query.userId);
});

app.use(async (context) => {
  context.res.body = await database.getOrdersByUser(context.user);
});

Azure Functions supports async functions and Azure Functions Middlewares handles everything needed in the function entrypoint generated by app.listen() method.

So, never call context.done().


Extending

Writing and publishing common middlewares

When we are talking about HTTP, some common middlewares is used by a lot of developers, just like authorization validation, content-type negotiation, parsing and output, and many more.

Azure Functions Middlewares doesn't have an API to extend it, because the middleware approach itself is extensible.

So, if you want to publish a middleware (or an evaluation function) you developed and think it will be useful for any other developer, fork this repository, add your middleware folder to the middlewares directory and make a pull request!

We will review it and publish it to the organization @azure-functions-middlewares.

Avaiable community middlewares

Middlewares officially developed by or reviwed by Azure Functions Middlewares maintainers are always under the @azure-functions-middlewares scope in NPM registry.


Help

Support

If you need help or have a problem with this project, start an issue.

We will not provide a SLA to your issue, so, don't expect it to be answered in a short time.


API

AzureFunctionCascade class

Properties

Returns all the middlewares added to the 'PRE_PROCESSING' phase.

Returns all the middlewares added to the 'MAIN' phase.

Returns all the middlewares added to the 'POST_PROCESSING' phase.

Methods

function(asyncMiddleware, phase?):AzureFunctionCascade

Adds a middleware to the middleware cascade.

Arguments

| Argument | Type | Required | Default | Description | | - | - | - | - | - | | asyncMiddleware | AsyncFunctionGenerator | true | | An asynchronous function that takes two arguments (context, STOP_SIGNAL) | | phase | 'PRE_PROCESSING' | 'MAIN' | 'POST_PROCESSING' | false | 'MAIN' | The cascade middlware phase that the middleware will be executed. |

Returns

AzureFunctionCascade the current instance of AzureFunctionCascade.

Callbacks

asyncMiddleware

async function (context, STOP_SIGNAL?):any

| Argument | Type | Required | Default | Description | | - | - | - | - | - | | context | Context | true | | The Azure Function context object. | | STOP_SIGNAL | '!STOP!' | null | false | | The constant value of a stop signal to return if you want to stop the middleware execution. |

Returns: anything returned by the middleware will be thrown as an error, except the STOP_SIGNAL constant.

function(expression, asyncMiddleware, phase?):AzureFunctionCascade

Adds a conditional middleware to the middleware cascade.

Arguments

| Argument | Type | Required | Default | Description | | - | - | - | - | - | | expression | function | true | | A function that takes a single argument (context) to check whether the middleware should be executed or not. | | asyncMiddleware | AsyncFunctionGenerator | true | | Same as in use() method. | | phase | 'PRE_PROCESSING' | 'MAIN' | 'POST_PROCESSING' | false | 'MAIN' | Same as in use() method. |

Returns

AzureFunctionCascade the current instance of AzureFunctionCascade.

Callbacks

expression

function (context):boolean

| Argument | Type | Required | Default | Description | | - | - | - | - | - | | context | Context | true | | The Azure Function context object. |

Returns: the expression must always return a boolean indicating if the middleware should be executed (true) or not (false).

asyncMiddleware

Same as in use() method.

function(catchCallback):AzureFunctionCascade

Registers an error callback to be called when a middleware throws an error.

Arguments

| Argument | Type | Required | Default | Description | | - | - | - | - | - | | catchCallback | function | true | | A callback function that takes one argument (context) |

Returns

AzureFunctionCascade the current instance of AzureFunctionCascade.

Callbacks

catchCallback

async function (context, STOP_SIGNAL?):any

| Argument | Type | Required | Default | Description | | - | - | - | - | - | | context | Context | true | | The Azure Function context object. |

Returns: anything returned by the callback will be ignored.

function():AzureFunction

Returns the Azure Functions entrypoint async (context) => {} that will be triggered by the function HTTP trigger and will execute the entire middleware cascade.

Returns

AzureFunction: the Azure Functions entrypoint.


Tecnhical concepts

Azure Functions Middlewares was inspired from famous middleware cascades for Node.js, like Express, Koa and HAPI.

Our goal is to provide easy functions shareability and reusing to the entire Azure Functions ecosystem and community.

We knew some similar solutions at the time of our development, but they lack some crucial features, like async support, middleware stop signal and execution phases.

The design of AzureFunctionCascade class inside the project's core is really simple. It is almost just three arrays of pipeline phases that are iterated when the function entrypoint is called by the Functions Host.

Features

  • Async middleware support
  • Error event middleware (a.k.a. "catch middleware")
  • Execution order customization (pre-execution, main execution and post-execution phases)
  • Middleware execution prevention (a.k.a. "stop signal")
  • Conditional middlewares

Related projects

  • azure-monofunction: A router solution to Azure Functions using a single function and Azure Functions Middlewares.

Similar projects


Contributing

If you don't want to code

Help us spreading the word or consider making a donation.

Star the project

Tweet it

Add your company to the used by section

Make a pull request or start an issue to add your company's name.

If you want to code

Code of conduct

We follow Contributor Covenant Code of Conduct. If you want to contribute to this project, you must accept and follow it.

SemVer

This project adheres to Semantic Versioning 2.0.0.

Roadmap

If you are not solving an issue or fixing a bug, you can help developing the roadmap below.

  • [ ] Improve docs/FAQ
  • [ ] Support async functions also on conditional evaluators and catch callback
  • [ ] Create a "priority" score to manually sort middlewares

Hall of fame

Used in production by companies


License

Licensed under the MIT License.