Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
@fastify/middie
Advanced tools
@fastify/middie is a Fastify plugin that allows you to use Express-style middleware in your Fastify application. This can be particularly useful for developers who are transitioning from Express to Fastify or who want to leverage existing middleware designed for Express.
Using Express Middleware
This feature allows you to use Express-style middleware in your Fastify application. The code sample demonstrates how to register the @fastify/middie plugin and use a simple middleware function that logs incoming requests.
const fastify = require('fastify')();
const middie = require('@fastify/middie');
fastify.register(middie).then(() => {
fastify.use((req, res, next) => {
console.log('Request received');
next();
});
fastify.get('/', (req, reply) => {
reply.send({ hello: 'world' });
});
fastify.listen(3000, err => {
if (err) throw err;
console.log('Server listening on http://localhost:3000');
});
});
Using Third-Party Middleware
This feature allows you to use third-party middleware designed for Express. The code sample demonstrates how to use the `cors` middleware to enable Cross-Origin Resource Sharing in your Fastify application.
const fastify = require('fastify')();
const middie = require('@fastify/middie');
const cors = require('cors');
fastify.register(middie).then(() => {
fastify.use(cors());
fastify.get('/', (req, reply) => {
reply.send({ hello: 'world' });
});
fastify.listen(3000, err => {
if (err) throw err;
console.log('Server listening on http://localhost:3000');
});
});
Chaining Multiple Middleware
This feature allows you to chain multiple middleware functions. The code sample demonstrates how to register multiple middleware functions that log messages to the console before handling a request.
const fastify = require('fastify')();
const middie = require('@fastify/middie');
fastify.register(middie).then(() => {
fastify.use((req, res, next) => {
console.log('First middleware');
next();
});
fastify.use((req, res, next) => {
console.log('Second middleware');
next();
});
fastify.get('/', (req, reply) => {
reply.send({ hello: 'world' });
});
fastify.listen(3000, err => {
if (err) throw err;
console.log('Server listening on http://localhost:3000');
});
});
fastify-express is a Fastify plugin that allows you to use Express middleware and routes within a Fastify application. It provides a similar functionality to @fastify/middie but also allows you to mount entire Express applications within Fastify.
fastify-plugin is a utility to help create Fastify plugins. While it does not directly provide middleware functionality, it is often used in conjunction with other packages to extend Fastify's capabilities, including middleware integration.
middie is a standalone middleware engine for Node.js that can be used with various frameworks, including Fastify. It provides a more generic approach to middleware management compared to @fastify/middie, which is specifically designed for Fastify.
@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.
npm i @fastify/middie
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)
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')())
}
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')
})
}
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')))
}
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.
You can also use the engine itself without the Fastify plugin system.
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
}
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)
}
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.
To use this module with TypeScript, make sure to install @types/connect
.
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 |
This project is kindly sponsored by:
Past sponsors:
Licensed under MIT.
FAQs
Middleware engine for Fastify
The npm package @fastify/middie receives a total of 328,653 weekly downloads. As such, @fastify/middie popularity was classified as popular.
We found that @fastify/middie demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.