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

@fastify/middie

v9.0.2

Published

Middleware engine for Fastify

Downloads

1,672,687

Readme

@fastify/middie

CI NPM version js-standard-style

@fastify/middie is the plugin that adds middleware support on steroids to Fastify.

The syntax style is the same as express/connect. Does not support the full syntax middleware(err, req, res, next), because error handling is done inside Fastify.

Install

npm i @fastify/middie

Usage

Register the plugin and start using your middleware.

const Fastify = require('fastify')

async function build () {
  const fastify = Fastify()
  await fastify.register(require('@fastify/middie'), {
    hook: 'onRequest' // default
  })
  // do you know we also have cors support?
  // https://github.com/fastify/fastify-cors
  fastify.use(require('cors')())
  return fastify
}

build()
  .then(fastify => fastify.listen({ port: 3000 }))
  .catch(console.log)

Encapsulation support

The encapsulation works as usual with Fastify, you can register the plugin in a subsystem and your code will work only inside there, or you can declare the middie plugin top level and register a middleware in a nested plugin, and the middleware will be executed only for the nested routes of the specific plugin.

Register the plugin in its own subsystem:

const fastify = require('fastify')()

fastify.register(subsystem)

async function subsystem (fastify, opts) {
  await fastify.register(require('@fastify/middie'))
  fastify.use(require('cors')())
}

Register a middleware in a specific plugin:

const fastify = require('fastify')()

fastify
  .register(require('@fastify/middie'))
  .register(subsystem)

async function subsystem (fastify, opts) {
  fastify.use(require('cors')())
}

Hooks and middleware

Every registered middleware will be run during the onRequest hook phase, so the registration order is important. Take a look at the Lifecycle documentation page to understand better how every request is executed.

const fastify = require('fastify')()

fastify
  .register(require('@fastify/middie'))
  .register(subsystem)

async function subsystem (fastify, opts) {
  fastify.addHook('onRequest', async (req, reply) => {
    console.log('first')
  })

  fastify.use((req, res, next) => {
    console.log('second')
    next()
  })

  fastify.addHook('onRequest', async (req, reply) => {
    console.log('third')
  })
}

It is possible to change the Fastify hook that the middleware will be attached to. Supported lifecycle hooks are:

  • onRequest
  • preParsing
  • preValidation
  • preHandler
  • preSerialization
  • onSend
  • onResponse
  • onError
  • onTimeout

To change the hook, pass a hook option like so:

Note you can access req.body from the preParsing, onError, preSerialization and onSend lifecycle steps. Take a look at the Lifecycle documentation page to see the order of the steps.

const fastify = require('fastify')()

fastify
  .register(require('@fastify/middie'), { hook: 'preHandler' })
  .register(subsystem)

async function subsystem (fastify, opts) {
  fastify.addHook('onRequest', async (req, reply) => {
    console.log('first')
  })

  fastify.use((req, res, next) => {
    console.log('third')
    next()
  })

  fastify.addHook('onRequest', async (req, reply) => {
    console.log('second')
  })

  fastify.addHook('preHandler', async (req, reply) => {
    console.log('fourth')
  })
}

Restrict middleware execution to a certain path(s)

If you need to run a middleware only under certain path(s), just pass the path as first parameter to use and you are done!

const fastify = require('fastify')()
const path = require('node:path')
const serveStatic = require('serve-static')

fastify
  .register(require('@fastify/middie'))
  .register(subsystem)

async function subsystem (fastify, opts) {
  // Single path
  fastify.use('/css', serveStatic(path.join(__dirname, '/assets')))

  // Wildcard path
  fastify.use('/css/*', serveStatic(path.join(__dirname, '/assets')))

  // Multiple paths
  fastify.use(['/css', '/js'], serveStatic(path.join(__dirname, '/assets')))
}

:warning: potential ReDoS attacks

Middie use path-to-regexp to convert paths to regular expressions. This might cause potential ReDoS attacks in your applications if certain patterns are used. Use it with care.

Middie Engine

You can also use the engine itself without the Fastify plugin system.

Usage

const Middie = require('@fastify/middie/engine')
const http = require('node:http')
const helmet = require('helmet')
const cors = require('cors')

const middie = Middie(_runMiddlewares)
middie.use(helmet())
middie.use(cors())

http
  .createServer(function handler (req, res) {
    middie.run(req, res)
  })
  .listen(3000)

function _runMiddlewares (err, req, res) {
  if (err) {
    console.log(err)
    res.end(err)
    return
  }

  // => routing function
}

Keep the context

If you need it you can also keep the context of the calling function by calling run with run(req, res, this), in this way you can avoid closures allocation.

http
  .createServer(function handler (req, res) {
    middie.run(req, res, { context: 'object' })
  })
  .listen(3000)

function _runMiddlewares (err, req, res, ctx) {
  if (err) {
    console.log(err)
    res.end(err)
    return
  }
  console.log(ctx)
}

Restrict middleware execution to a certain path(s)

If you need to run a middleware only under certains path(s), just pass the path as first parameter to use and you are done!

Note that this does support routes with parameters, e.g. /user/:id/comments, but all the matched parameters will be discarded

// Single path
middie.use('/public', staticFiles('/assets'))

// Multiple middleware
middie.use('/public', [cors(), staticFiles('/assets')])

// Multiple paths
middie.use(['/public', '/dist'], staticFiles('/assets'))

// Multiple paths and multiple middleware
middie.use(['/public', '/dist'], [cors(), staticFiles('/assets')])

To guarantee compatibility with Express, adding a prefix uses path-to-regexp to compute a RegExp, which is then used to math every request: it is significantly slower.

TypeScript support

To use this module with TypeScript, make sure to install @types/connect.

Middleware alternatives

Fastify offers some alternatives to the most commonly used Express middleware:

| Express Middleware | Fastify Plugin | | ------------- |---------------| | helmet | fastify-helmet | | cors | fastify-cors | | serve-static | fastify-static |

Acknowledgements

This project is kindly sponsored by:

Past sponsors:

License

Licensed under MIT.