File size: 7,699 Bytes
23ac194
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# V4 Migration Guide

This guide is intended to help with migration from Fastify v3 to v4.

Before migrating to v4, please ensure that you have fixed all deprecation
warnings from v3. All v3 deprecations have been removed and they will no longer
work after upgrading.

## Codemods
### Fastify v4 Codemods

To help with the upgrade, we’ve worked with the team at
[Codemod](https://github.com/codemod-com/codemod) to
publish codemods that will automatically update your code to many of
the new APIs and patterns in Fastify v4.

Run the following
[migration recipe](https://go.codemod.com/fastify-4-migration-recipe) to
automatically update your code to Fastify v4:

```
npx codemod@latest fastify/4/migration-recipe
```

This will run the following codemods:

- [`fastify/4/remove-app-use`](https://go.codemod.com/fastify-4-remove-app-use)
- [`fastify/4/reply-raw-access`](https://go.codemod.com/fastify-4-reply-raw-access)
- [`fastify/4/wrap-routes-plugin`](https://go.codemod.com/fastify-4-wrap-routes-plugin)
- [`fastify/4/await-register-calls`](https://go.codemod.com/fastify-4-await-register-calls)

Each of these codemods automates the changes listed in the v4 migration guide.
For a complete list of available Fastify codemods and further details,
see [Codemod Registry](https://go.codemod.com/fastify).


## Breaking Changes

### Error handling composition ([#3261](https://github.com/fastify/fastify/pull/3261))

When an error is thrown in an async error handler function, the upper-level
error handler is executed if set. If there is no upper-level error handler,
the default will be executed as it was previously:

```js
import Fastify from 'fastify'

const fastify = Fastify()

fastify.register(async fastify => {
  fastify.setErrorHandler(async err => {
    console.log(err.message) // 'kaboom'
    throw new Error('caught')
  })

  fastify.get('/encapsulated', async () => {
    throw new Error('kaboom')
  })
})

fastify.setErrorHandler(async err => {
  console.log(err.message) // 'caught'
  throw new Error('wrapped')
})

const res = await fastify.inject('/encapsulated')
console.log(res.json().message) // 'wrapped'
```

>The root error handler is Fastify’s generic error handler.
>This error handler will use the headers and status code in the Error object,
>if they exist. **The headers and status code will not be automatically set if
>a custom error handler is provided**.

### Removed `app.use()` ([#3506](https://github.com/fastify/fastify/pull/3506))

With v4 of Fastify, `app.use()` has been removed and the use of middleware is
no longer supported.

If you need to use middleware, use
[`@fastify/middie`](https://github.com/fastify/middie) or
[`@fastify/express`](https://github.com/fastify/fastify-express), which will
continue to be maintained.
However, it is strongly recommended that you migrate to Fastify's [hooks](../Reference/Hooks.md).

> **Note**: Codemod remove `app.use()` with:
>
> ```bash
> npx codemod@latest fastify/4/remove-app-use
> ```

### `reply.res` moved to `reply.raw`

If you previously used the `reply.res` attribute to access the underlying Request
object you will now need to use `reply.raw`.

> **Note**: Codemod `reply.res` to `reply.raw` with:
>
> ```bash
> npx codemod@latest fastify/4/reply-raw-access
> ```

### Need to `return reply` to signal a "fork" of the promise chain

In some situations, like when a response is sent asynchronously or when you are
not explicitly returning a response, you will now need to return the `reply`
argument from your router handler.

### `exposeHeadRoutes` true by default

Starting with v4, every `GET` route will create a sibling `HEAD` route.
You can revert this behavior by setting `exposeHeadRoutes: false` in the server options.

### Synchronous route definitions ([#2954](https://github.com/fastify/fastify/pull/2954))

To improve error reporting in route definitions, route registration is now synchronous.
As a result, if you specify an `onRoute` hook in a plugin you should now either:
* wrap your routes in a plugin (recommended)

  For example, refactor this:
  ```js
  fastify.register((instance, opts, done) => {
    instance.addHook('onRoute', (routeOptions) => {
      const { path, method } = routeOptions;
      console.log({ path, method });
      done();
    });
  });

  fastify.get('/', (request, reply) => { reply.send('hello') });
  ```

  Into this:
  ```js
  fastify.register((instance, opts, done) => {
    instance.addHook('onRoute', (routeOptions) => {
      const { path, method } = routeOptions;
      console.log({ path, method });
      done();
    });
  });

  fastify.register((instance, opts, done) => {
    instance.get('/', (request, reply) => { reply.send('hello') });
    done();
  });
  ```
> **Note**: Codemod synchronous route definitions with:
>
> ```bash
> npx codemod@latest fastify/4/wrap-routes-plugin
> ```

* use `await register(...)`

  For example, refactor this:
  ```js
  fastify.register((instance, opts, done) => {
    instance.addHook('onRoute', (routeOptions) => {
      const { path, method } = routeOptions;
      console.log({ path, method });
    });
    done();
  });
  ```

  Into this:
  ```js
  await fastify.register((instance, opts, done) => {
    instance.addHook('onRoute', (routeOptions) => {
      const { path, method } = routeOptions;
      console.log({ path, method });
    });
    done();
  });
  ```

> **Note**: Codemod 'await register(...)' with:
>
> ```bash
> npx codemod@latest fastify/4/await-register-calls
> ```


### Optional URL parameters

If you've already used any implicitly optional parameters, you'll get a 404
error when trying to access the route. You will now need to declare the
optional parameters explicitly.

For example, if you have the same route for listing and showing a post,
refactor this:
```js
fastify.get('/posts/:id', (request, reply) => {
  const { id } = request.params;
});
```

Into this:
```js
fastify.get('/posts/:id?', (request, reply) => {
  const { id } = request.params;
});
```

## Non-Breaking Changes

### Deprecation of variadic `.listen()` signature

The [variadic signature](https://en.wikipedia.org/wiki/Variadic_function) of the
`fastify.listen()` method is now deprecated.

Prior to this release, the following invocations of this method were valid:

  - `fastify.listen(8000)`
  - `fastify.listen(8000, ‘127.0.0.1’)`
  - `fastify.listen(8000, ‘127.0.0.1’, 511)`
  - `fastify.listen(8000, (err) => { if (err) throw err })`
  - `fastify.listen({ port: 8000 }, (err) => { if (err) throw err })`

With Fastify v4, only the following invocations are valid:

  - `fastify.listen()`
  - `fastify.listen({ port: 8000 })`
  - `fastify.listen({ port: 8000 }, (err) => { if (err) throw err })`

### Change of schema for multiple types

Ajv has been upgraded to v8 in Fastify v4, meaning "type" keywords with multiple
types other than "null"
[are now prohibited](https://ajv.js.org/strict-mode.html#strict-types).

You may encounter a console warning such as:
```sh
strict mode: use allowUnionTypes to allow union type keyword at "#/properties/image" (strictTypes)
```

As such, schemas like below will need to be changed from:
```js
{
  type: 'object',
  properties: {
    api_key: { type: 'string' },
    image: { type: ['object', 'array'] }
  }
}
```

Into:
```js
{
  type: 'object',
  properties: {
    api_key: { type: 'string' },
    image: {
      anyOf: [
        { type: 'array' },
        { type: 'object' }
      ]
    }
  }
}
```

### Add `reply.trailers` methods ([#3794](https://github.com/fastify/fastify/pull/3794))

Fastify now supports the [HTTP Trailer] response headers.


[HTTP Trailer]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Trailer