Fastify v2.0.0 is here

In November we released the first Release Candidate of Fastify v2, and we never thought it would take us more than 3 months to be able to graduate v2 out of the RC phase. 6 releases and 85 pull requests later, here we are!

Courtesy of Mikhail Vasilyev

In these three months, we focused on porting all modules maintained in the Fastify github organization to v2, and we were able to make more changes and bug fixes that would be breaking changes.

You can install it now with npm install fastify. Most plugins would need to be updated, but there will be a new update for them as well!

Speaking of new features and breaking changes, following you can find the list of all the major changes we did, with the link to their pull request, a brief description, and a code example.

Let us know about any compatibility and upgrade issues at https://github.com/fastify/help.

Added onError hook #1236

Add a new application hook called onError, which a developer can use to track all the errors that Fastify is sending to the user. This can be super useful also for sending errors to an external tracer or to support an APM (Application Performance Monitoring) solution.
In Fastify v1 we can’t do that easily because the setErrorHandler can be overwritten and the onSend hook receives the already serialized payload.
In Fastify v1 there is no way to get the error object and be 100% sure that your code will never be overwritten.

fastify.addHook(‘onError’, async (request, reply, error) => {
// some code
})

Move all _ prefixed properties to Symbols in next #1237 #1128

Internal fastify properties that were prefixed with _ in key objects, such as Request and Reply, are now using Symbols. This provides a more clear separation between the internals and your application, clearly identifying which properties you can use.

Plugins can now receive both /prefix and prefix/ #1228

The ability to prefix all the routes defined in a plugin is a key feature of Fastify. In v2 we have resolved a problem that made it impossible to set up a route for both /prefix and /prefix/, as follows:

const fastify = require(‘fastify’)()
fastify.register(async function (instance, options) {
// the route will be called for both ‘/english/’ and ‘/english’
instance.get(‘/’, async (req, reply) => {
return { greet: ‘hello’ }
})
}, { prefix: ‘/english’ })
fastify.listen(8000)

Default error handler that logs the error #1135

In Fastify v1, we logged all errors independently if there was (or not) a custom error handler (via setErrorHandler()). In Fastify v2, this behavior has been moved to the error handler. This means that an error handler is now responsible for logging the error itself.

fastify.setErrorHandler(function (error, request, reply) {
request.log.warn(error) // this is needed now
var statusCode = error.statusCode >= 400 ? error.statusCode : 500
reply
.code(statusCode)
.type(‘text/plain’)
.send(statusCode >= 500
? ‘Internal server error’
: error.message
)
})

Ensure Reply#serialize uses custom serializer #1163

reply.serialize(payload) serializes the payload using the custom serializer, if one is set.

Better error management #1168

We can sum up this new feature with one word: standardization!
From Fastify v2 the errors will no longer be generated inline, but they will be instances of custom errors classes.
You can access the full error list from require('fastify/errors') .

Bumped avvio to 6.0.0 #1201

The new version of avvio removes the instance from the onClose hook as the first parameter.

fastify.addHook('onClose', (done) => {
// some code
done()
})

Added preParsing hook #1377

This hook was needed because there was no way to run the authentication logic before the validation but after the onRequest hook or the middlewares. There are cases where you may not want to expose your validation logic to unauthenticated requests, this hook fixes that issue.

fastify.addHook(‘preParsing’, async function (request, reply) {
// request and reply are the core Fastify objects
})

Added preValidation hook #1153

This hook was needed because there was no way to run execute logic after parsing a payload but before the validation. There are cases where you may want to massage your data before validation, as an example do some security checks.

fastify.addHook('preValidation', async (request, reply) => {
// some code
})

Added preSerialization hook and route option #1408

If you are using the `preSerialization` hook, you can change (or replace) the payload before it is serialized. For example:

fastify.addHook('preSerialization', 
async (request, reply, payload) => {
return { wrapped: payload }
})

Change basePath to prefix #1183

A basePath property was populated with the prefix option when passed to a plugin. This has now been renamed to prefix, to provide a more intuitive API. The use of basePath is now deprecated.

Separate logging and reqId options #1164 #1166

From Fastify v2 you must create the custom request id as a top-level option in the Fastify configuration, and no longer inside the logger configuration. This is still supported, but Fastify will log a warning. The option will be dropped from Fastify v3.

Change the default plugin timeout to 10 seconds instead of 0 #1145

Each plugin now has 10 seconds to load or it will error. This solves a long-standing issue with Fastify’s bootstrapping phase: forgetting to call a callback or resolving a promise would lead to a stuck load phase with no way to easily debug it.

Pino v5 #1065

Fastify now uses Pino v5 internally, for better and more performant logging with zero cost log redaction. Check it out at https://www.nearform.com/blog/announcing-pino-v5-0-0/.

As an example, the following snippet will print all the incoming headers but the authorization.

const fastify = require(‘fastify’)({
logger: {
stream: stream,
redact: [‘req.headers.authorization’],
level: ‘info’,
serializers: {
req(req) {
return {
method: req.method,
url: req.url,
headers: req.headers,
hostname: req.hostname,
remoteAddress: req.ip,
remotePort: req.connection.remotePort
}
}
}
}
})

Drop @types/pino from dependencies #1366

Fastify now ships its own types for the logger because there were discrepancies in the implementation when the logger was enabled or not. If access to the full pino API is needed, it is still possible to cast them using @types/pino. As a good bonus, removing this dependency shrinked the size of our bundle.

Updated Not found handling #1084

If one of your routes returns a 404 error, from Fastify v2 will be handled by the customErrorHandler and not the notFoundHandler. You can still route requests to the notFoundHandler via reply.callNotFound(). The notFoundHandler will be used only for router generated 404s.

Hooks: always use Fastify core objects #1066

This was a long-awaited “feature”, in Fastify v1 onRequest and onResponsehave different signature and objects, which leads to confusion and slightly complex internals.

From Fastify v2 we have fixed that, and now every hook will expose the exact same signature. The middlewares will continue to expose the default Node.js core objects to allow compatibility with Express middlewares. If you are not using Express middlewares, we highly recommend using Fastify hooks.

fastify.addHook(‘onRequest’, async function (request, reply) {
// request and reply are the core Fastify objects
})
fastify.addHook(‘onResponse’, async function (request, reply) {
// request and reply are the core Fastify objects
})
fastify.use(function (req, res, next) {
// req and res are the Node core objects
next()
})

Remove `req.id` in serializer #1032

There is no more the req.id property in the logs, but only reqId (less duplication, less space, more speed!).

Removed url.parse and added custom querystring parser support #1270

Since url.parse will be deprecated from Node.js v12, we decided to remove it from the codebase and use the Node.js’s core querystring module instead. With this change, the querystring parsing is twice faster than before!
We have also exposed a new configuration option (querystringParser) to change the default querystring parser if needed.

Extended support of cross-platform builds and yarn official support #1226

Due to the extended support of Azure pipelines, our CI is more performant and we are able to test cross-platform (Linux/yarn and Windows/npm) with a single setup in a timely fashion. This also brings official yarn support for Node 8 and Node 10. We thank AppVeyor for the support in the last year of Windows testing. We are also keeping our travis-ci integration for Linux/npm for the time being.

Add plain text parser to core #1280

Fastify now support parsing the ‘text/plain’ content-type out of the box.

Default ajv instance to include all errors #1398

Validation errors returned from Fastify default Ajv instance will now return the full errors.

Courtesy of Fred F.

Acknowledgments

More than 1900 commits, more than 100 releases, more than 550 forks, used in production by more than 13 companies, more than 400k downloads, and 93 officially recognized plugins.

All this work wouldn’t be possible without the help of our fantastic team, which we would like to thank for all their hard work!
allevo, cemremengu, delvedor, evanshortiss, lmammino, jsumners, mcollina, nwoltman, starptech, trivikr, and Ethan-Arrowood.
We also want to thank all of our amazing contributors, for all the bug reporting, pull requests and for have believed in our project!

Fastify v2 is covered by our LTS support cycle, organized as follows: at least six months of active support starting now, plus six months of security fixes (after the release of Fastify v3), while Fastify v1 will reach EOL on September first.

Happy coding!

The Fastify Team