Description
Summary
hapi v19.0.0 is a small size release with a few changes to improve performance, support for multiple versions of joi schemas, and standards compliance.
- Upgrade time: low - none to a couple of hours for most users
- Complexity: low - requires following the list of changes to verifying their impact
- Risk: low - small number of changes with simple ways to retain previous behavior in most cases
- Dependencies: medium - most existing plugins will work as-is, however plugins with scoped names might require changes to retain scope in exposed plugin APIs
Breaking Changes
- Only support node v12 or newer. Will not work at all on node v11 or older (Drop support for node v8 #3910, Drop node 10 #4012, Use private class fields #4013).
request.payload
is initialized toundefined
inonResponse
and if modified, will cause payload processing to bypass (Do not override request.payload if set manually in onRequest #4015).server.expose()
when used in a plugin with a scoped name (e.g.@hapi/example
) will no longer include the scope (e.g.@hapi/
) prefix inserver.plugins
, unless the newscope
option is set (Change scoped plugins name handling #4011).- No joi schema compiler is loaded by default and must be explicitly loaded using
server.validator(require('@hapi/joi'))
if uncompiled schemas are using in configuration (server.validator() #4006). - Remove support for request queueing (
server.load.concurrent
) (Remove request queue (options.load.concurrent) #3977). - Change the route
options.payload.multipart
tofalse
by default (Change routes.payload.multipart to false by default #3920). - Change default empty status code to
204
from200
(Change emptyStatusCode to 204 by default #3919). request.info.remoteAddress
andrequest.info.remotePort
are only populated upon access.
New Features
- Support multiple joi schema compilers at the same time allowing each plugin to specify the version of joi it is using (server.validator() #4006).
- Support
SameSite=None
and the ability to customize cookie settings per-request in runtime which is required for some Chrome 80 migrations (Support SameSite=None for cookies #3987). - Always include auth artifacts regardless of auth status (auth scheme artifacts are dropped when mode is not 'try' #4000).
Bug fixes
- Support request decorations using symbols and runtime apply (Decorate requests with symbols with apply=true #3996).
Migration Checklist
Node version
Make sure your node version is v12.14.1 or newer. This release uses language features that are only available in node v12 or higher and will not even start on older versions. Node v12 is the current LTS and the recommended version of node.
Request payload override
The request.payload
property is now initialized to undefined
instead of null
when accessed in an onResponse
extension handler. If modified, it will cause payload processing to bypass instead of just being overridden later by the framework.
Checklist:
- Look for
request.payload
access inonRequest
handlers and make sure you are not expectingnull
specifically. If the value is being modified, note that it will now "stick".
Exposed plugin APIs
When using server.expose()
in a plugin with a scoped name (e.g. @hapi/example
), the object key set under server.plugins
will no longer include the scope (e.g. @hapi/
), unless the new scope
option is set. This may only impact your code if you are using scoped plugins.
Checklist:
- Look for references to
server.plugins['@
which will need to be updated to exclude the plugin scope or upgrade your plugin module to a newer version designed to work with hapi v19 and explicitly set the handling of scope prefixes. - If you are a plugin author (public or private) and would like to keep the scopes in the exposed API path, add the new
{ scope: true }
option as the third argument toserver.expose()
.
joi Schema Compiler
In previous versions, hapi included a built-in joi schema compiler that allowed setting validation rules without a top level joi wrapper:
{
validate: {
payload: {
name: Joi.string().required()
}
}
}
instead of the explicit version which is more verbose and less readable:
{
validate: {
payload: Joi.object({
name: Joi.string().required()
})
}
}
The inclusion of a default schema compiler caused problems every time the version of the compiler changed and forced developers to update their schemas.
This release removes the default compiler and adds a new server.validator()
method which takes a direct reference to the joi module used. It only sets the compiler for the current realm and its sub-realms, allowing each plugin to specify it's own validation compiler and not worry about mixing versions.
Checklist:
- Check your code for route
validate
andresponse.schema
settings and if you are passing values that must be compiled (see above for the lack ofJoi.object()
as a typical case), either wrap your schema withJoi.object()
or callserver.validator(Joi)
.
Remove support for request queueing
This rarely used feature was removed without a replacement.
Checklist:
- Look for
server.load.concurrent
configuration and remove it.
Change route options.payload.multipart
to false
by default
Route configuration default was change to disable multipart processing. You will need to either enable it for the entire server to keep previous behavior or just for the routes where multipart processing is required.
Change default empty status code to 204
The HTTP standard defines a 204 status code for responses with an empty payload. In previous versions of the framework, empty responses used the 200
status code unless the emptyStatusCode
configuration option was explicitly set to 204
. The new default is 204
which can be explicitly set to 200
.
This change mostly affect tests and some strict API clients that check the status code to be exactly 200
vs any 2xx
response. If you are not sure about it or rather not deal with it, simply set emptyStatusCode
back to 200
.
Checklist:
- Look for existing
emptyStatusCode
configuration. If it is set to204
you can remove it (or leave it). If there is no configuration and you would like to keep previous behavior add a server level config withemptyStatusCode
set to200
.
request.info.remoteAddress
and request.info.remotePort
The properties have been changed to use getters and are only populated when requested. This is a performance optimization as those are slow calls that should only be performed when actually needed. The breaking change is due to the fact that these values are no longer available if the request is aborted.
Checklist:
- If you rely on the -
request.info.remoteAddress
andrequest.info.remotePort
properties when requests are aborted, use the routeinfo.remote
settings set totrue
.