Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/fastify/middie
Middleware engine for Fastify.
https://github.com/fastify/middie
fastify fastify-plugin middlewares performances
Last synced: about 1 month ago
JSON representation
Middleware engine for Fastify.
- Host: GitHub
- URL: https://github.com/fastify/middie
- Owner: fastify
- License: mit
- Created: 2017-02-11T00:33:51.000Z (almost 8 years ago)
- Default Branch: master
- Last Pushed: 2024-05-01T22:10:06.000Z (7 months ago)
- Last Synced: 2024-05-22T02:42:36.891Z (6 months ago)
- Topics: fastify, fastify-plugin, middlewares, performances
- Language: JavaScript
- Homepage:
- Size: 185 KB
- Stars: 234
- Watchers: 16
- Forks: 25
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# @fastify/middie
![CI](https://github.com/fastify/middie/workflows/CI/badge.svg)
[![NPM version](https://img.shields.io/npm/v/@fastify/middie.svg?style=flat)](https://www.npmjs.com/package/@fastify/middie)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://standardjs.com/)*@fastify/middie* is the plugin that adds middleware support on steroids to [Fastify](https://www.npmjs.com/package/fastify).
The syntax style is the same as [express](http://npm.im/express)/[connect](https://www.npmjs.com/package/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.
```js
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:*
```js
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:*
```js
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](https://fastify.dev/docs/latest/Reference/Lifecycle/) documentation page to understand better how every request is executed.```js
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](https://www.fastify.dev/docs/latest/Reference/Lifecycle/) documentation page to see the order of the steps.*
```js
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!
```js
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`](http://npm.im/path-to-regexp) to convert paths to regular expressions.
This might cause potential [ReDoS](https://en.wikipedia.org/wiki/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
```js
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.```js
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*
```js
// 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`](https://www.npmjs.com/package/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`](https://github.com/helmetjs/helmet) | [`fastify-helmet`](https://github.com/fastify/fastify-helmet) |
| [`cors`](https://github.com/expressjs/cors) | [`fastify-cors`](https://github.com/fastify/fastify-cors) |
| [`serve-static`](https://github.com/expressjs/serve-static) | [`fastify-static`](https://github.com/fastify/fastify-static) |## Acknowledgements
This project is kindly sponsored by:
- [nearForm](https://nearform.com)Past sponsors:
- [LetzDoIt](https://www.letzdoitapp.com/)## License
Licensed under [MIT](./LICENSE).