fastify 3.14.0 → 3.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -6
- package/SECURITY.md +2 -2
- package/docs/Benchmarking.md +1 -1
- package/docs/Ecosystem.md +8 -0
- package/docs/Hooks.md +7 -3
- package/docs/Logging.md +1 -1
- package/docs/Migration-Guide-V3.md +1 -1
- package/docs/Routes.md +1 -1
- package/docs/Server.md +5 -6
- package/docs/Serverless.md +4 -4
- package/docs/Style-Guide.md +1 -1
- package/docs/TypeScript.md +136 -7
- package/docs/Validation-and-Serialization.md +6 -6
- package/fastify.d.ts +4 -3
- package/fastify.js +1 -1
- package/lib/reply.js +24 -13
- package/lib/route.js +1 -1
- package/package.json +2 -2
- package/test/hooks-async.test.js +46 -0
- package/test/hooks.test.js +47 -0
- package/test/schema-serialization.test.js +42 -0
- package/test/schema-special-usage.test.js +52 -0
- package/test/types/content-type-parser.test-d.ts +8 -2
- package/test/types/instance.test-d.ts +21 -1
- package/types/content-type-parser.d.ts +6 -0
- package/types/instance.d.ts +27 -4
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<img src="https://github.com/fastify/graphics/raw/
|
|
2
|
+
<img src="https://github.com/fastify/graphics/raw/HEAD/full-logo.png" width="650" height="auto"/>
|
|
3
3
|
</div>
|
|
4
4
|
|
|
5
5
|
<div align="center">
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
[](https://github.com/fastify/fastify/actions/workflows/package-manager-ci.yml)
|
|
9
9
|
[](https://github.com/fastify/fastify/actions/workflows/website.yml)
|
|
10
10
|
[](https://snyk.io/test/github/fastify/fastify)
|
|
11
|
-
[](https://coveralls.io/github/fastify/fastify?branch=main)
|
|
12
12
|
[](https://standardjs.com/)
|
|
13
13
|
|
|
14
14
|
</div>
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
[](https://www.npmjs.com/package/fastify)
|
|
19
19
|
[](https://www.npmjs.com/package/fastify)
|
|
20
20
|
[](https://github.com/nodejs/security-wg/blob/
|
|
21
|
+
Disclosure](https://img.shields.io/badge/Security-Responsible%20Disclosure-yellow.svg)](https://github.com/nodejs/security-wg/blob/HEAD/processes/responsible_disclosure_template.md)
|
|
22
22
|
[](https://discord.gg/fastify)
|
|
23
23
|
|
|
24
24
|
</div>
|
|
@@ -191,7 +191,7 @@ matters to you.
|
|
|
191
191
|
* <a href="./docs/Serverless.md"><code><b>Serverless</b></code></a>
|
|
192
192
|
* <a href="./docs/Recommendations.md"><code><b>Recommendations</b></code></a>
|
|
193
193
|
|
|
194
|
-
中文文档[地址](https://github.com/fastify/docs-chinese/blob/
|
|
194
|
+
中文文档[地址](https://github.com/fastify/docs-chinese/blob/HEAD/README.md)
|
|
195
195
|
|
|
196
196
|
## Ecosystem
|
|
197
197
|
|
|
@@ -238,6 +238,7 @@ Team members are listed in alphabetical order.
|
|
|
238
238
|
* [__Vincent Le Goff__](https://github.com/zekth)
|
|
239
239
|
* [__Salman Mitha__](https://github.com/salmanm), <https://www.npmjs.com/~salmanm>
|
|
240
240
|
* [__Maksim Sinik__](https://github.com/fox1t), <https://twitter.com/maksimsinik>, <https://www.npmjs.com/~fox1t>
|
|
241
|
+
* [__Frazer Smith__](https://github.com/Fdawgs), <https://www.npmjs.com/~fdawgs>
|
|
241
242
|
* [__Manuel Spigolon__](https://github.com/eomm), <https://twitter.com/manueomm>, <https://www.npmjs.com/~eomm>
|
|
242
243
|
|
|
243
244
|
### Great Contributors
|
|
@@ -255,9 +256,9 @@ Great contributors on a specific area in the Fastify ecosystem will be invited t
|
|
|
255
256
|
|
|
256
257
|
## Hosted by
|
|
257
258
|
|
|
258
|
-
[<img src="https://github.com/openjs-foundation/cross-project-council/blob/
|
|
259
|
+
[<img src="https://github.com/openjs-foundation/cross-project-council/blob/HEAD/logos/openjsf-color.png?raw=true" width="250px;"/>](https://openjsf.org/projects/#growth)
|
|
259
260
|
|
|
260
|
-
We are a [Growth Project](https://github.com/openjs-foundation/cross-project-council/blob/
|
|
261
|
+
We are a [Growth Project](https://github.com/openjs-foundation/cross-project-council/blob/HEAD/PROJECT_PROGRESSION.md#growth-stage) in the [OpenJS Foundation](https://openjsf.org/).
|
|
261
262
|
|
|
262
263
|
## Acknowledgements
|
|
263
264
|
|
package/SECURITY.md
CHANGED
|
@@ -9,7 +9,7 @@ Individuals who find potential vulnerabilities in Fastify are invited to complet
|
|
|
9
9
|
|
|
10
10
|
### How to report a vulnerability
|
|
11
11
|
|
|
12
|
-
It is of the utmost importance that you read carefully [**HOW TO REPORT A VULNERABILITY**](https://github.com/nodejs/security-wg/blob/
|
|
12
|
+
It is of the utmost importance that you read carefully [**HOW TO REPORT A VULNERABILITY**](https://github.com/nodejs/security-wg/blob/HEAD/processes/third_party_vuln_process.md) written by the Security Working Group of Node.js.
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
## Handling vulnerability reports
|
|
@@ -24,7 +24,7 @@ When a potential vulnerability is reported and confirmed the Fastify Core Team w
|
|
|
24
24
|
|
|
25
25
|
## The Fastify Core team
|
|
26
26
|
|
|
27
|
-
The core team is responsible for the management of [this](https://github.com/nodejs/security-wg/blob/
|
|
27
|
+
The core team is responsible for the management of [this](https://github.com/nodejs/security-wg/blob/HEAD/processes/third_party_vuln_process.md#handling-vulnerability-reports) process.
|
|
28
28
|
|
|
29
29
|
Members of this team are expected to keep all information that they have privileged access to by being
|
|
30
30
|
on the team completely private to the team. This includes agreeing to not notify anyone outside the
|
package/docs/Benchmarking.md
CHANGED
|
@@ -33,7 +33,7 @@ branchcmp --rounds 2 --script "npm run benchmark"
|
|
|
33
33
|
branchcmp --rounds 2 --script "npm run benchmark"
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
### Compare current branch with
|
|
36
|
+
### Compare current branch with main (Gitflow)
|
|
37
37
|
```sh
|
|
38
38
|
branchcmp --rounds 2 --gitflow --script "npm run benchmark"
|
|
39
39
|
```
|
package/docs/Ecosystem.md
CHANGED
|
@@ -57,12 +57,19 @@ Plugins maintained by the Fastify team are listed under [Core](#core) while plug
|
|
|
57
57
|
- [`@dnlup/fastify-doc`](https://github.com/dnlup/fastify-doc) A plugin for sampling process metrics.
|
|
58
58
|
- [`@dnlup/fastify-traps`](https://github.com/dnlup/fastify-traps) A plugin to close the server gracefully on `SIGINT` and `SIGTERM` signals.
|
|
59
59
|
- [`@gquittet/graceful-server`](https://github.com/gquittet/graceful-server) Tiny (~5k), Fast, KISS and dependency-free Node.JS library to make your Fastify API graceful.
|
|
60
|
+
- [`@mgcrea/fastify-graceful-exit`](https://github.com/mgcrea/fastify-graceful-exit) A plugin to close the server gracefully
|
|
61
|
+
- [`@mgcrea/fastify-request-logger`](https://github.com/mgcrea/fastify-request-logger) A plugin to enable compact request logging for fastify
|
|
62
|
+
- [`@mgcrea/fastify-session-redis-store`](https://github.com/mgcrea/fastify-session-redis-store) Redis store for @mgcrea/fastify-session using ioredis
|
|
63
|
+
- [`@mgcrea/fastify-session-sodium-crypto`](https://github.com/mgcrea/fastify-session-sodium-crypto) Fast sodium-based crypto for @mgcrea/fastify-session
|
|
64
|
+
- [`@mgcrea/fastify-session`](https://github.com/mgcrea/fastify-session) Session plugin for fastify that supports both stateless and sateful sessions
|
|
65
|
+
- [`@mgcrea/pino-pretty-compact`](https://github.com/mgcrea/pino-pretty-compact) A custom compact pino-base prettifier
|
|
60
66
|
- [`apollo-server-fastify`](https://github.com/apollographql/apollo-server/tree/master/packages/apollo-server-fastify) Run an [Apollo Server](https://github.com/apollographql/apollo-server) to serve GraphQL with Fastify.
|
|
61
67
|
- [`arecibo`](https://github.com/nucleode/arecibo) Fastify ping responder for Kubernetes Liveness and Readiness Probes.
|
|
62
68
|
- [`cls-rtracer`](https://github.com/puzpuzpuz/cls-rtracer) Fastify middleware for CLS-based request id generation. An out-of-the-box solution for adding request ids into your logs.
|
|
63
69
|
- [`fastify-405`](https://github.com/Eomm/fastify-405) Fastify plugin that adds 405 HTTP status to your routes
|
|
64
70
|
- [`fastify-amqp`](https://github.com/RafaelGSS/fastify-amqp) Fastify AMQP connection plugin, to use with RabbitMQ or another connector. Just a wrapper to [`amqplib`](https://github.com/squaremo/amqp.node).
|
|
65
71
|
- [`fastify-angular-universal`](https://github.com/exequiel09/fastify-angular-universal) Angular server-side rendering support using [`@angular/platform-server`](https://github.com/angular/angular/tree/master/packages/platform-server) for Fastify
|
|
72
|
+
- [`fastify-api-key`](https://github.com/arkerone/fastify-api-key) Fastify plugin to authenticate HTTP requests based on api key and signature
|
|
66
73
|
- [`fastify-auth0-verify`](https://github.com/nearform/fastify-auth0-verify): Auth0 verification plugin for Fastify, internally uses [fastify-jwt](https://npm.im/fastify-jwt) and [jsonwebtoken](https://npm.im/jsonwebtoken).
|
|
67
74
|
- [`fastify-autocrud`](https://github.com/paranoiasystem/fastify-autocrud) Plugin to autogenerate CRUD routes as fast as possible.
|
|
68
75
|
- [`fastify-autoroutes`](https://github.com/GiovanniCardamone/fastify-autoroutes) Plugin to scan and load routes based on filesystem path from custom directory.
|
|
@@ -169,6 +176,7 @@ Plugins maintained by the Fastify team are listed under [Core](#core) while plug
|
|
|
169
176
|
- [`fastify-twitch-ebs-tools`](https://github.com/lukemnet/fastify-twitch-ebs-tools) Useful functions for Twitch Extension Backend Services (EBS).
|
|
170
177
|
- [`fastify-typeorm-plugin`](https://github.com/inthepocket/fastify-typeorm-plugin) Fastify plugin to work with TypeORM.
|
|
171
178
|
- [`fastify-vhost`](https://github.com/patrickpissurno/fastify-vhost) Proxy subdomain http requests to another server (useful if you want to point multiple subdomains to the same IP address, while running different servers on the same machine).
|
|
179
|
+
- [`fastify-vite`](https://github.com/galvez/fastify-vite) [Vite](https://vitejs.dev/) plugin for Fastify with SSR data support.
|
|
172
180
|
- [`fastify-vue-plugin`](https://github.com/TheNoim/fastify-vue) [Nuxt.js](https://nuxtjs.org) plugin for Fastify. Control the routes nuxt should use.
|
|
173
181
|
- [`fastify-wamp-router`](https://github.com/lependu/fastify-wamp-router) Web Application Messaging Protocol router for Fastify.
|
|
174
182
|
- [`fast-water`](https://github.com/tswayne/fast-water) A Fastify plugin for waterline. Decorates Fastify with waterline models.
|
package/docs/Hooks.md
CHANGED
|
@@ -85,19 +85,23 @@ fastify.addHook('preParsing', async (request, reply, payload) => {
|
|
|
85
85
|
**Notice**: The old syntaxes `function(request, reply, done)` and `async function(request, reply)` for the parser are still supported but they are deprecated.
|
|
86
86
|
|
|
87
87
|
### preValidation
|
|
88
|
+
|
|
89
|
+
If you are using the `preValidation` hook, you can change the payload before it is validated. For example:
|
|
90
|
+
|
|
88
91
|
```js
|
|
89
92
|
fastify.addHook('preValidation', (request, reply, done) => {
|
|
90
|
-
|
|
93
|
+
req.body = { ...req.body, importantKey: 'randomString' }
|
|
91
94
|
done()
|
|
92
95
|
})
|
|
93
96
|
```
|
|
94
97
|
Or `async/await`:
|
|
95
98
|
```js
|
|
96
99
|
fastify.addHook('preValidation', async (request, reply) => {
|
|
97
|
-
|
|
98
|
-
|
|
100
|
+
const importantKey = await generateRandomString()
|
|
101
|
+
req.body = { ...req.body, importantKey }
|
|
99
102
|
})
|
|
100
103
|
```
|
|
104
|
+
|
|
101
105
|
### preHandler
|
|
102
106
|
```js
|
|
103
107
|
fastify.addHook('preHandler', (request, reply, done) => {
|
package/docs/Logging.md
CHANGED
|
@@ -59,7 +59,7 @@ const fastify = require('fastify')({
|
|
|
59
59
|
|
|
60
60
|
By default, fastify adds an id to every request for easier tracking. If the "request-id" header is present its value is used, otherwise a new incremental id is generated. See Fastify Factory [`requestIdHeader`](Server.md#factory-request-id-header) and Fastify Factory [`genReqId`](Server.md#gen-request-id) for customization options.
|
|
61
61
|
|
|
62
|
-
The default logger is configured with a set of standard serializers that serialize objects with `req`, `res`, and `err` properties. The object received by `req` is the Fastify [`Request`](Request.md) object, while the object received by `res` is the Fastify [`Reply`](Reply.md) object.
|
|
62
|
+
The default logger is configured with a set of standard serializers that serialize objects with `req`, `res`, and `err` properties. The object received by `req` is the Fastify [`Request`](Request.md) object, while the object received by `res` is the Fastify [`Reply`](Reply.md) object.
|
|
63
63
|
This behaviour can be customized by specifying custom serializers.
|
|
64
64
|
```js
|
|
65
65
|
const fastify = require('fastify')({
|
|
@@ -267,7 +267,7 @@ fastify.get('/', (request, reply) => {
|
|
|
267
267
|
|
|
268
268
|
## Further additions and improvements
|
|
269
269
|
|
|
270
|
-
- Hooks now have consistent context
|
|
270
|
+
- Hooks now have consistent context regardless of how they are registered
|
|
271
271
|
([#2005](https://github.com/fastify/fastify/pull/2005))
|
|
272
272
|
- Deprecated `request.req` and `reply.res` for [`request.raw`](Request.md) and
|
|
273
273
|
[`reply.raw`](Reply.md) ([#2008](https://github.com/fastify/fastify/pull/2008))
|
package/docs/Routes.md
CHANGED
|
@@ -416,7 +416,7 @@ Fastify supports constraining routes to match only certain requests based on som
|
|
|
416
416
|
#### Version Constraints
|
|
417
417
|
|
|
418
418
|
You can provide a `version` key in the `constraints` option to a route. Versioned routes allows you to declare multiple handlers for the same HTTP route path which will then be matched according to each request's `Accept-Version` header. The `Accept-Version` header value should follow the [semver](http://semver.org/) specification, and routes should be declared with exact semver versions for matching.<br/>
|
|
419
|
-
Fastify will require a request `Accept-Version` header to be set if the route has a version set, and will prefer a versioned route to a non-versioned route for the same path. Advanced version ranges
|
|
419
|
+
Fastify will require a request `Accept-Version` header to be set if the route has a version set, and will prefer a versioned route to a non-versioned route for the same path. Advanced version ranges and pre-releases currently are not supported.<br/>
|
|
420
420
|
*Be aware that using this feature will cause a degradation of the overall performances of the router.*
|
|
421
421
|
|
|
422
422
|
```js
|
package/docs/Server.md
CHANGED
|
@@ -4,10 +4,9 @@
|
|
|
4
4
|
## Factory
|
|
5
5
|
|
|
6
6
|
The Fastify module exports a factory function that is used to create new
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
available in that options object.
|
|
7
|
+
<code><b>Fastify server</b></code> instances. This factory function accepts
|
|
8
|
+
an options object which is used to customize the resulting instance. This
|
|
9
|
+
document describes the properties available in that options object.
|
|
11
10
|
|
|
12
11
|
<a name="factory-http2"></a>
|
|
13
12
|
### `http2`
|
|
@@ -192,7 +191,7 @@ fastify.addHook('onResponse', (req, reply, done) => {
|
|
|
192
191
|
})
|
|
193
192
|
```
|
|
194
193
|
|
|
195
|
-
Please note that this setting will also disable an error log written by the
|
|
194
|
+
Please note that this setting will also disable an error log written by the default `onResponse` hook on reply callback errors.
|
|
196
195
|
|
|
197
196
|
<a name="custom-http-server"></a>
|
|
198
197
|
### `serverFactory`
|
|
@@ -986,7 +985,7 @@ fastify.ready(() => {
|
|
|
986
985
|
<a name="addContentTypeParser"></a>
|
|
987
986
|
#### addContentTypeParser
|
|
988
987
|
|
|
989
|
-
`fastify.addContentTypeParser(content-type, options, parser)` is used to pass custom parser for a given content type. Useful for adding parsers for custom content types, e.g. `text/json, application/vnd.oasis.opendocument.text`. `content-type` can be a string
|
|
988
|
+
`fastify.addContentTypeParser(content-type, options, parser)` is used to pass custom parser for a given content type. Useful for adding parsers for custom content types, e.g. `text/json, application/vnd.oasis.opendocument.text`. `content-type` can be a string, string array or RegExp.
|
|
990
989
|
|
|
991
990
|
```js
|
|
992
991
|
// The two arguments passed to getDefaultJsonParser are for ProtoType poisoning and Constructor Poisoning configuration respectively. The possible values are 'ignore', 'remove', 'error'. ignore skips all validations and it is similar to calling JSON.parse() directly. See the <a href="https://github.com/fastify/secure-json-parse#api">`secure-json-parse` documentation</a> for more information.
|
package/docs/Serverless.md
CHANGED
|
@@ -269,7 +269,7 @@ module.exports = {
|
|
|
269
269
|
|
|
270
270
|
### Scripts
|
|
271
271
|
|
|
272
|
-
Add this command to your `package.json` *scripts*
|
|
272
|
+
Add this command to your `package.json` *scripts*
|
|
273
273
|
|
|
274
274
|
```json
|
|
275
275
|
"scripts": {
|
|
@@ -291,9 +291,9 @@ configuring your `vercel.json` file like the following:
|
|
|
291
291
|
```json
|
|
292
292
|
{
|
|
293
293
|
"rewrites": [
|
|
294
|
-
{
|
|
295
|
-
"source": "/(.*)",
|
|
296
|
-
"destination": "/api/serverless.js"
|
|
294
|
+
{
|
|
295
|
+
"source": "/(.*)",
|
|
296
|
+
"destination": "/api/serverless.js"
|
|
297
297
|
}
|
|
298
298
|
]
|
|
299
299
|
}
|
package/docs/Style-Guide.md
CHANGED
|
@@ -163,7 +163,7 @@ Here is how your hyperlink should look:
|
|
|
163
163
|
```MD
|
|
164
164
|
<!-- More like this -->
|
|
165
165
|
|
|
166
|
-
// Add clear &
|
|
166
|
+
// Add clear & brief description
|
|
167
167
|
[Fastify Plugins] (https://www.fastify.io/docs/latest/Plugins/)
|
|
168
168
|
|
|
169
169
|
<!--Less like this -->
|
package/docs/TypeScript.md
CHANGED
|
@@ -98,6 +98,7 @@ The type system heavily relies on generic properties to provide the most accurat
|
|
|
98
98
|
return `logged in!`
|
|
99
99
|
})
|
|
100
100
|
```
|
|
101
|
+
|
|
101
102
|
4. Build and run the server code with `npm run build` and `npm run start`
|
|
102
103
|
5. Query the api
|
|
103
104
|
```bash
|
|
@@ -126,14 +127,80 @@ The type system heavily relies on generic properties to provide the most accurat
|
|
|
126
127
|
|
|
127
128
|
### JSON Schema
|
|
128
129
|
|
|
130
|
+
To validate your requests and responses you can use JSON Schema files. If you didn't know already, defining schemas for your Fastify routes can increase their throughput! Check out the [Validation and Serialization](Validation-and-Serialization.md) documentation for more info.
|
|
131
|
+
|
|
132
|
+
Also it has the advantage to use the defined type within your handlers (including pre-validation, etc.).
|
|
133
|
+
|
|
134
|
+
Here are some options how to achieve this.
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
#### typebox
|
|
138
|
+
|
|
139
|
+
A useful library for building types and a schema at once is [typebox](https://www.npmjs.com/package/@sinclair/typebox).
|
|
140
|
+
With typebox you define your schema within your code and use them directly as types or schemas as you need them.
|
|
141
|
+
|
|
142
|
+
When you want to use it for validation of some payload in a fastify route you can do it as follows:
|
|
143
|
+
|
|
144
|
+
1. Install `typebox` in your project.
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
npm i @sinclair/typebox
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
2. Define the schema you need with `Type` and create the respective type with `Static`.
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
import { Static, Type } from '@sinclair/typebox'
|
|
154
|
+
|
|
155
|
+
const User = Type.Object({
|
|
156
|
+
name: Type.String(),
|
|
157
|
+
mail: Type.Optional(Type.String({ format: "email" })),
|
|
158
|
+
});
|
|
159
|
+
type UserType = Static<typeof User>;
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
3. Use the defined type and schema during the definition of your route
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
const app = fastify();
|
|
166
|
+
|
|
167
|
+
app.post<{ Body: UserType; Response: UserType }>(
|
|
168
|
+
"/",
|
|
169
|
+
{
|
|
170
|
+
schema: {
|
|
171
|
+
body: User,
|
|
172
|
+
response: {
|
|
173
|
+
200: User,
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
(req, rep) => {
|
|
178
|
+
const { body: user } = req;
|
|
179
|
+
/* user has type
|
|
180
|
+
* const user: StaticProperties<{
|
|
181
|
+
* name: TString;
|
|
182
|
+
* mail: TOptional<TString>;
|
|
183
|
+
* }>
|
|
184
|
+
*/
|
|
185
|
+
//...
|
|
186
|
+
rep.status(200).send(user);
|
|
187
|
+
}
|
|
188
|
+
);
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
#### Schemas in JSON Files
|
|
192
|
+
|
|
129
193
|
In the last example we used interfaces to define the types for the request querystring and headers. Many users will already be using JSON Schemas to define these properties, and luckily there is a way to transform existing JSON Schemas into TypeScript interfaces!
|
|
130
194
|
|
|
131
195
|
1. If you did not complete the 'Getting Started' example, go back and follow steps 1-4 first.
|
|
132
196
|
2. Install the `json-schema-to-typescript` module:
|
|
133
|
-
|
|
197
|
+
|
|
198
|
+
```bash
|
|
134
199
|
npm i -D json-schema-to-typescript
|
|
135
200
|
```
|
|
201
|
+
|
|
136
202
|
3. Create a new folder called `schemas` and add two files `headers.json` and `querystring.json`. Copy and paste the following schema definitions into the respective files:
|
|
203
|
+
|
|
137
204
|
```json
|
|
138
205
|
{
|
|
139
206
|
"title": "Headers Schema",
|
|
@@ -145,6 +212,7 @@ In the last example we used interfaces to define the types for the request query
|
|
|
145
212
|
"required": ["h-Custom"]
|
|
146
213
|
}
|
|
147
214
|
```
|
|
215
|
+
|
|
148
216
|
```json
|
|
149
217
|
{
|
|
150
218
|
"title": "Querystring Schema",
|
|
@@ -157,18 +225,22 @@ In the last example we used interfaces to define the types for the request query
|
|
|
157
225
|
"required": ["username", "password"]
|
|
158
226
|
}
|
|
159
227
|
```
|
|
228
|
+
|
|
160
229
|
4. Add a `compile-schemas` script to the package.json:
|
|
161
|
-
|
|
230
|
+
|
|
231
|
+
```json
|
|
162
232
|
{
|
|
163
233
|
"scripts": {
|
|
164
234
|
"compile-schemas": "json2ts -i schemas -o types"
|
|
165
235
|
}
|
|
166
236
|
}
|
|
167
|
-
|
|
237
|
+
```
|
|
238
|
+
|
|
168
239
|
`json2ts` is a CLI utility included in `json-schema-to-typescript`. `schemas` is the input path, and `types` is the output path.
|
|
169
240
|
5. Run `npm run compile-schemas`. Two new files should have been created in the `types` directory.
|
|
170
241
|
6. Update `index.ts` to have the following code:
|
|
171
|
-
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
172
244
|
import fastify from 'fastify'
|
|
173
245
|
|
|
174
246
|
// import json schemas as normal
|
|
@@ -229,10 +301,67 @@ In the last example we used interfaces to define the types for the request query
|
|
|
229
301
|
```
|
|
230
302
|
Pay special attention to the imports at the top of this file. It might seem redundant, but you need to import both the schema files and the generated interfaces.
|
|
231
303
|
|
|
232
|
-
Great work! Now you can make use of both JSON Schemas and TypeScript definitions.
|
|
304
|
+
Great work! Now you can make use of both JSON Schemas and TypeScript definitions.
|
|
305
|
+
|
|
306
|
+
#### json-schema-to-ts
|
|
233
307
|
|
|
234
|
-
|
|
235
|
-
-
|
|
308
|
+
If you do not want to generate types from your schemas, but want to use them diretly from your code, you can use the package
|
|
309
|
+
[json-schema-to-ts](https://www.npmjs.com/package/json-schema-to-ts).
|
|
310
|
+
|
|
311
|
+
You can install it as dev-dependency.
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
npm install -D json-schema-to-ts
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
In your code you can define your schema like a normal object. But be aware of making it *const* like explained in the docs of the module.
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
const todo = {
|
|
321
|
+
type: 'object',
|
|
322
|
+
properties: {
|
|
323
|
+
name: { type: 'string' },
|
|
324
|
+
description: { type: 'string' },
|
|
325
|
+
done: { type: 'boolean' },
|
|
326
|
+
},
|
|
327
|
+
required: ['name'],
|
|
328
|
+
} as const;
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
With the provided type `FromSchema` you can build a type from your schema and use it in your handler.
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
fastify.post<{ Body: FromSchema<typeof todo> }>(
|
|
335
|
+
'/todo',
|
|
336
|
+
{
|
|
337
|
+
schema: {
|
|
338
|
+
body: todo,
|
|
339
|
+
response: {
|
|
340
|
+
201: {
|
|
341
|
+
type: 'string',
|
|
342
|
+
},
|
|
343
|
+
},
|
|
344
|
+
}
|
|
345
|
+
},
|
|
346
|
+
async (request, reply): Promise<void> => {
|
|
347
|
+
|
|
348
|
+
/*
|
|
349
|
+
request.body has type
|
|
350
|
+
{
|
|
351
|
+
[x: string]: unknown;
|
|
352
|
+
description?: string;
|
|
353
|
+
done?: boolean;
|
|
354
|
+
name: string;
|
|
355
|
+
}
|
|
356
|
+
*/
|
|
357
|
+
|
|
358
|
+
request.body.name // will not throw type error
|
|
359
|
+
request.body.notthere // will throw type error
|
|
360
|
+
|
|
361
|
+
reply.status(201).send();
|
|
362
|
+
},
|
|
363
|
+
);
|
|
364
|
+
```
|
|
236
365
|
|
|
237
366
|
### Plugins
|
|
238
367
|
|
|
@@ -101,7 +101,7 @@ As usual, the function `getSchemas` is encapsulated and returns the shared schem
|
|
|
101
101
|
```js
|
|
102
102
|
fastify.addSchema({ $id: 'one', my: 'hello' })
|
|
103
103
|
// will return only `one` schema
|
|
104
|
-
fastify.get('/', (request, reply) => { reply.send(fastify.getSchemas()) })
|
|
104
|
+
fastify.get('/', (request, reply) => { reply.send(fastify.getSchemas()) })
|
|
105
105
|
|
|
106
106
|
fastify.register((instance, opts, done) => {
|
|
107
107
|
instance.addSchema({ $id: 'two', my: 'ciao' })
|
|
@@ -544,10 +544,10 @@ const schema = {
|
|
|
544
544
|
and fail to satisfy it, the route will immediately return a response with the following payload
|
|
545
545
|
|
|
546
546
|
```js
|
|
547
|
-
{
|
|
547
|
+
{
|
|
548
548
|
"statusCode": 400,
|
|
549
549
|
"error": "Bad Request",
|
|
550
|
-
"message": "body should have required property 'name'"
|
|
550
|
+
"message": "body should have required property 'name'"
|
|
551
551
|
}
|
|
552
552
|
```
|
|
553
553
|
|
|
@@ -575,7 +575,7 @@ The context function will be the Fastify server instance.
|
|
|
575
575
|
```js
|
|
576
576
|
const fastify = Fastify({
|
|
577
577
|
schemaErrorFormatter: (errors, dataVar) => {
|
|
578
|
-
// ... my formatting logic
|
|
578
|
+
// ... my formatting logic
|
|
579
579
|
return new Error(myErrorMessage)
|
|
580
580
|
}
|
|
581
581
|
})
|
|
@@ -583,7 +583,7 @@ const fastify = Fastify({
|
|
|
583
583
|
// or
|
|
584
584
|
fastify.setSchemaErrorFormatter(function (errors, dataVar) {
|
|
585
585
|
this.log.error({ err: errors }, 'Validation failed')
|
|
586
|
-
// ... my formatting logic
|
|
586
|
+
// ... my formatting logic
|
|
587
587
|
return new Error(myErrorMessage)
|
|
588
588
|
})
|
|
589
589
|
```
|
|
@@ -598,7 +598,7 @@ fastify.setErrorHandler(function (error, request, reply) {
|
|
|
598
598
|
})
|
|
599
599
|
```
|
|
600
600
|
|
|
601
|
-
If you want custom error response in schema without headaches and quickly, you can take a look at [`ajv-errors`](https://github.com/epoberezkin/ajv-errors). Checkout the [example](https://github.com/fastify/example/blob/
|
|
601
|
+
If you want custom error response in schema without headaches and quickly, you can take a look at [`ajv-errors`](https://github.com/epoberezkin/ajv-errors). Checkout the [example](https://github.com/fastify/example/blob/HEAD/validation-messages/custom-errors-messages.js) usage.
|
|
602
602
|
|
|
603
603
|
Below is an example showing how to add **custom error messages for each property** of a schema by supplying custom AJV options.
|
|
604
604
|
Inline comments in the schema below describe how to configure it to show a different error message for each case:
|
package/fastify.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ import * as ajv from 'ajv'
|
|
|
13
13
|
import { FastifyError } from 'fastify-error'
|
|
14
14
|
import { FastifyReply } from './types/reply'
|
|
15
15
|
import { FastifySchemaValidationError } from './types/schema'
|
|
16
|
+
import { ConstructorAction, ProtoAction } from "./types/content-type-parser";
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Fastify factory function for the standard fastify http, https, or http2 server instance.
|
|
@@ -88,8 +89,8 @@ export type FastifyServerOptions<
|
|
|
88
89
|
maxParamLength?: number,
|
|
89
90
|
disableRequestLogging?: boolean,
|
|
90
91
|
exposeHeadRoutes?: boolean,
|
|
91
|
-
onProtoPoisoning?:
|
|
92
|
-
onConstructorPoisoning?:
|
|
92
|
+
onProtoPoisoning?: ProtoAction,
|
|
93
|
+
onConstructorPoisoning?: ConstructorAction,
|
|
93
94
|
logger?: boolean | FastifyLoggerOptions<RawServer> | Logger,
|
|
94
95
|
serverFactory?: FastifyServerFactory<RawServer>,
|
|
95
96
|
caseSensitive?: boolean,
|
|
@@ -152,7 +153,7 @@ export { FastifyLoggerOptions, FastifyLoggerInstance, FastifyLogFn, LogLevel } f
|
|
|
152
153
|
export { FastifyContext } from './types/context'
|
|
153
154
|
export { RouteHandler, RouteHandlerMethod, RouteOptions, RouteShorthandMethod, RouteShorthandOptions, RouteShorthandOptionsWithHandler } from './types/route'
|
|
154
155
|
export * from './types/register'
|
|
155
|
-
export { FastifyBodyParser, FastifyContentTypeParser, AddContentTypeParser, hasContentTypeParser } from './types/content-type-parser'
|
|
156
|
+
export { FastifyBodyParser, FastifyContentTypeParser, AddContentTypeParser, hasContentTypeParser, getDefaultJsonParser, ProtoAction, ConstructorAction } from './types/content-type-parser'
|
|
156
157
|
export { FastifyError } from 'fastify-error'
|
|
157
158
|
export { FastifySchema, FastifySchemaCompiler } from './types/schema'
|
|
158
159
|
export { HTTPMethods, RawServerBase, RawRequestDefaultExpression, RawReplyDefaultExpression, RawServerDefault, ContextConfigDefault, RequestBodyDefault, RequestQuerystringDefault, RequestParamsDefault, RequestHeadersDefault } from './types/utils'
|
package/fastify.js
CHANGED
|
@@ -540,7 +540,7 @@ function fastify (options) {
|
|
|
540
540
|
|
|
541
541
|
// Most devs do not know what to do with this error.
|
|
542
542
|
// In the vast majority of cases, it's a network error and/or some
|
|
543
|
-
// config issue on the
|
|
543
|
+
// config issue on the load balancer side.
|
|
544
544
|
this.log.trace({ err }, 'client error')
|
|
545
545
|
|
|
546
546
|
// If the socket is not writable, there is no reason to try to send data.
|
package/lib/reply.js
CHANGED
|
@@ -539,19 +539,30 @@ function handleError (reply, error, cb) {
|
|
|
539
539
|
return
|
|
540
540
|
}
|
|
541
541
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
542
|
+
let payload
|
|
543
|
+
try {
|
|
544
|
+
const serializerFn = getSchemaSerializer(reply.context, statusCode)
|
|
545
|
+
payload = (serializerFn === false)
|
|
546
|
+
? serializeError({
|
|
547
|
+
error: statusCodes[statusCode + ''],
|
|
548
|
+
code: error.code,
|
|
549
|
+
message: error.message || '',
|
|
550
|
+
statusCode: statusCode
|
|
551
|
+
})
|
|
552
|
+
: serializerFn(Object.create(error, {
|
|
553
|
+
error: { value: statusCodes[statusCode + ''] },
|
|
554
|
+
message: { value: error.message || '' },
|
|
555
|
+
statusCode: { value: statusCode }
|
|
556
|
+
}))
|
|
557
|
+
} catch (err) {
|
|
558
|
+
reply.log.error({ err, statusCode: res.statusCode }, 'The serializer for the given status code failed')
|
|
559
|
+
res.statusCode = 500
|
|
560
|
+
payload = serializeError({
|
|
561
|
+
error: statusCodes['500'],
|
|
562
|
+
message: err.message || '',
|
|
563
|
+
statusCode: 500
|
|
564
|
+
})
|
|
565
|
+
}
|
|
555
566
|
|
|
556
567
|
flatstr(payload)
|
|
557
568
|
reply[kReplyHeaders]['content-type'] = CONTENT_TYPE.JSON
|
package/lib/route.js
CHANGED
|
@@ -298,7 +298,7 @@ function buildRouting (options) {
|
|
|
298
298
|
context.schema = normalizeSchema(context.schema)
|
|
299
299
|
|
|
300
300
|
const schemaController = this[kSchemaController]
|
|
301
|
-
if (!opts.validatorCompiler) {
|
|
301
|
+
if (!opts.validatorCompiler && (opts.schema.body || opts.schema.headers || opts.schema.querystring || opts.schema.params)) {
|
|
302
302
|
schemaController.setupValidator(this[kOptions])
|
|
303
303
|
}
|
|
304
304
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fastify",
|
|
3
|
-
"version": "3.14.
|
|
3
|
+
"version": "3.14.1",
|
|
4
4
|
"description": "Fast and low overhead web framework, for Node.js",
|
|
5
5
|
"main": "fastify.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -177,7 +177,7 @@
|
|
|
177
177
|
"abstract-logging": "^2.0.0",
|
|
178
178
|
"ajv": "^6.12.2",
|
|
179
179
|
"avvio": "^7.1.2",
|
|
180
|
-
"fast-json-stringify": "^2.5.
|
|
180
|
+
"fast-json-stringify": "^2.5.2",
|
|
181
181
|
"fastify-error": "^0.3.0",
|
|
182
182
|
"fastify-warning": "^0.2.0",
|
|
183
183
|
"find-my-way": "^4.0.0",
|
package/test/hooks-async.test.js
CHANGED
|
@@ -318,6 +318,52 @@ test('preValidation hooks should be able to block a request', t => {
|
|
|
318
318
|
})
|
|
319
319
|
})
|
|
320
320
|
|
|
321
|
+
test('preValidation hooks should be able to change request body before validation', t => {
|
|
322
|
+
t.plan(4)
|
|
323
|
+
const fastify = Fastify()
|
|
324
|
+
|
|
325
|
+
fastify.addHook('preValidation', async (req, _reply) => {
|
|
326
|
+
const buff = Buffer.from(req.body.message, 'base64')
|
|
327
|
+
req.body = JSON.parse(buff.toString('utf-8'))
|
|
328
|
+
})
|
|
329
|
+
|
|
330
|
+
fastify.post(
|
|
331
|
+
'/',
|
|
332
|
+
{
|
|
333
|
+
schema: {
|
|
334
|
+
body: {
|
|
335
|
+
type: 'object',
|
|
336
|
+
properties: {
|
|
337
|
+
foo: {
|
|
338
|
+
type: 'string'
|
|
339
|
+
},
|
|
340
|
+
bar: {
|
|
341
|
+
type: 'number'
|
|
342
|
+
}
|
|
343
|
+
},
|
|
344
|
+
required: ['foo', 'bar']
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
},
|
|
348
|
+
(req, reply) => {
|
|
349
|
+
t.pass()
|
|
350
|
+
reply.status(200).send('hello')
|
|
351
|
+
}
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
fastify.inject({
|
|
355
|
+
url: '/',
|
|
356
|
+
method: 'POST',
|
|
357
|
+
payload: {
|
|
358
|
+
message: Buffer.from(JSON.stringify({ foo: 'example', bar: 1 })).toString('base64')
|
|
359
|
+
}
|
|
360
|
+
}, (err, res) => {
|
|
361
|
+
t.error(err)
|
|
362
|
+
t.is(res.statusCode, 200)
|
|
363
|
+
t.is(res.payload, 'hello')
|
|
364
|
+
})
|
|
365
|
+
})
|
|
366
|
+
|
|
321
367
|
test('preSerialization hooks should be able to modify the payload', t => {
|
|
322
368
|
t.plan(3)
|
|
323
369
|
const fastify = Fastify()
|
package/test/hooks.test.js
CHANGED
|
@@ -1437,6 +1437,53 @@ test('preValidation hooks should be able to block a request', t => {
|
|
|
1437
1437
|
})
|
|
1438
1438
|
})
|
|
1439
1439
|
|
|
1440
|
+
test('preValidation hooks should be able to change request body before validation', t => {
|
|
1441
|
+
t.plan(4)
|
|
1442
|
+
const fastify = Fastify()
|
|
1443
|
+
|
|
1444
|
+
fastify.addHook('preValidation', (req, _reply, done) => {
|
|
1445
|
+
const buff = Buffer.from(req.body.message, 'base64')
|
|
1446
|
+
req.body = JSON.parse(buff.toString('utf-8'))
|
|
1447
|
+
done()
|
|
1448
|
+
})
|
|
1449
|
+
|
|
1450
|
+
fastify.post(
|
|
1451
|
+
'/',
|
|
1452
|
+
{
|
|
1453
|
+
schema: {
|
|
1454
|
+
body: {
|
|
1455
|
+
type: 'object',
|
|
1456
|
+
properties: {
|
|
1457
|
+
foo: {
|
|
1458
|
+
type: 'string'
|
|
1459
|
+
},
|
|
1460
|
+
bar: {
|
|
1461
|
+
type: 'number'
|
|
1462
|
+
}
|
|
1463
|
+
},
|
|
1464
|
+
required: ['foo', 'bar']
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
},
|
|
1468
|
+
(req, reply) => {
|
|
1469
|
+
t.pass()
|
|
1470
|
+
reply.status(200).send('hello')
|
|
1471
|
+
}
|
|
1472
|
+
)
|
|
1473
|
+
|
|
1474
|
+
fastify.inject({
|
|
1475
|
+
url: '/',
|
|
1476
|
+
method: 'POST',
|
|
1477
|
+
payload: {
|
|
1478
|
+
message: Buffer.from(JSON.stringify({ foo: 'example', bar: 1 })).toString('base64')
|
|
1479
|
+
}
|
|
1480
|
+
}, (err, res) => {
|
|
1481
|
+
t.error(err)
|
|
1482
|
+
t.is(res.statusCode, 200)
|
|
1483
|
+
t.is(res.payload, 'hello')
|
|
1484
|
+
})
|
|
1485
|
+
})
|
|
1486
|
+
|
|
1440
1487
|
test('preParsing hooks should be able to block a request', t => {
|
|
1441
1488
|
t.plan(5)
|
|
1442
1489
|
const fastify = Fastify()
|
|
@@ -498,3 +498,45 @@ test('The schema changes the default error handler output', async t => {
|
|
|
498
498
|
t.equals(res.statusCode, 500)
|
|
499
499
|
t.deepEquals(res.json(), { error: 'Internal Server Error', message: '500 message', customId: 42 })
|
|
500
500
|
})
|
|
501
|
+
|
|
502
|
+
test('do not crash if status code serializer errors', async t => {
|
|
503
|
+
const fastify = Fastify()
|
|
504
|
+
|
|
505
|
+
const requiresFoo = {
|
|
506
|
+
properties: { foo: { type: 'string' } },
|
|
507
|
+
required: ['foo']
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
const someUserErrorType2 = {
|
|
511
|
+
properties: {
|
|
512
|
+
code: { type: 'number' }
|
|
513
|
+
},
|
|
514
|
+
required: ['code']
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
fastify.get(
|
|
518
|
+
'/',
|
|
519
|
+
{
|
|
520
|
+
schema: {
|
|
521
|
+
query: requiresFoo,
|
|
522
|
+
response: { 400: someUserErrorType2 }
|
|
523
|
+
}
|
|
524
|
+
},
|
|
525
|
+
(request, reply) => {
|
|
526
|
+
t.fail('handler, should not be called')
|
|
527
|
+
}
|
|
528
|
+
)
|
|
529
|
+
|
|
530
|
+
const res = await fastify.inject({
|
|
531
|
+
path: '/',
|
|
532
|
+
query: {
|
|
533
|
+
notfoo: true
|
|
534
|
+
}
|
|
535
|
+
})
|
|
536
|
+
t.equals(res.statusCode, 500)
|
|
537
|
+
t.deepEquals(res.json(), {
|
|
538
|
+
statusCode: 500,
|
|
539
|
+
error: 'Internal Server Error',
|
|
540
|
+
message: '"code" is required!'
|
|
541
|
+
})
|
|
542
|
+
})
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { test } = require('tap')
|
|
4
4
|
const AJV = require('ajv')
|
|
5
|
+
const S = require('fluent-json-schema')
|
|
5
6
|
const Fastify = require('..')
|
|
6
7
|
const ajvMergePatch = require('ajv-merge-patch')
|
|
7
8
|
|
|
@@ -403,3 +404,54 @@ test('side effect on schema let the server crash', async t => {
|
|
|
403
404
|
|
|
404
405
|
await fastify.ready()
|
|
405
406
|
})
|
|
407
|
+
|
|
408
|
+
test('only response schema trigger AJV pollution', async t => {
|
|
409
|
+
const ShowSchema = S.object().id('ShowSchema').prop('name', S.string())
|
|
410
|
+
const ListSchema = S.array().id('ListSchema').items(S.ref('ShowSchema#'))
|
|
411
|
+
|
|
412
|
+
const fastify = Fastify()
|
|
413
|
+
fastify.addSchema(ListSchema)
|
|
414
|
+
fastify.addSchema(ShowSchema)
|
|
415
|
+
|
|
416
|
+
const routeResponseSchemas = {
|
|
417
|
+
schema: { response: { 200: S.ref('ListSchema#') } }
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
fastify.register(
|
|
421
|
+
async (app) => { app.get('/resource/', routeResponseSchemas, () => ({})) },
|
|
422
|
+
{ prefix: '/prefix1' }
|
|
423
|
+
)
|
|
424
|
+
fastify.register(
|
|
425
|
+
async (app) => { app.get('/resource/', routeResponseSchemas, () => ({})) },
|
|
426
|
+
{ prefix: '/prefix2' }
|
|
427
|
+
)
|
|
428
|
+
|
|
429
|
+
await fastify.ready()
|
|
430
|
+
})
|
|
431
|
+
|
|
432
|
+
test('only response schema trigger AJV pollution #2', async t => {
|
|
433
|
+
const ShowSchema = S.object().id('ShowSchema').prop('name', S.string())
|
|
434
|
+
const ListSchema = S.array().id('ListSchema').items(S.ref('ShowSchema#'))
|
|
435
|
+
|
|
436
|
+
const fastify = Fastify()
|
|
437
|
+
fastify.addSchema(ListSchema)
|
|
438
|
+
fastify.addSchema(ShowSchema)
|
|
439
|
+
|
|
440
|
+
const routeResponseSchemas = {
|
|
441
|
+
schema: {
|
|
442
|
+
params: S.ref('ListSchema#'),
|
|
443
|
+
response: { 200: S.ref('ListSchema#') }
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
fastify.register(
|
|
448
|
+
async (app) => { app.get('/resource/', routeResponseSchemas, () => ({})) },
|
|
449
|
+
{ prefix: '/prefix1' }
|
|
450
|
+
)
|
|
451
|
+
fastify.register(
|
|
452
|
+
async (app) => { app.get('/resource/', routeResponseSchemas, () => ({})) },
|
|
453
|
+
{ prefix: '/prefix2' }
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
await fastify.ready()
|
|
457
|
+
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import fastify from '../../fastify'
|
|
2
|
-
import { expectType } from 'tsd'
|
|
1
|
+
import fastify, { FastifyContentTypeParser } from '../../fastify'
|
|
2
|
+
import { expectError, expectType } from 'tsd'
|
|
3
3
|
import { IncomingMessage } from 'http'
|
|
4
4
|
import { FastifyRequest } from '../../types/request'
|
|
5
5
|
|
|
@@ -56,3 +56,9 @@ expectType<void>(fastify().addContentTypeParser<Buffer>('bodyContentType', { par
|
|
|
56
56
|
expectType<Buffer>(body)
|
|
57
57
|
return null
|
|
58
58
|
}))
|
|
59
|
+
|
|
60
|
+
expectType<FastifyContentTypeParser>(fastify().getDefaultJsonParser('error', 'ignore'))
|
|
61
|
+
|
|
62
|
+
expectError(fastify().getDefaultJsonParser('error', 'skip'))
|
|
63
|
+
|
|
64
|
+
expectError(fastify().getDefaultJsonParser('nothing', 'ignore'))
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import fastify, { FastifyError, FastifyInstance, ValidationResult } from '../../fastify'
|
|
1
|
+
import fastify, { FastifyContentTypeParser, FastifyError, FastifyInstance, ValidationResult } from '../../fastify'
|
|
2
2
|
import { expectAssignable, expectError, expectType } from 'tsd'
|
|
3
|
+
import { FastifyRequest } from '../../types/request'
|
|
4
|
+
import { FastifyReply } from '../../types/reply'
|
|
5
|
+
import { HookHandlerDoneFunction } from '../../types/hooks'
|
|
3
6
|
|
|
4
7
|
const server = fastify()
|
|
5
8
|
|
|
@@ -38,6 +41,19 @@ server.setErrorHandler(fastifyErrorHandler)
|
|
|
38
41
|
function nodeJSErrorHandler (error: NodeJS.ErrnoException) {}
|
|
39
42
|
server.setErrorHandler(nodeJSErrorHandler)
|
|
40
43
|
|
|
44
|
+
function notFoundHandler (request: FastifyRequest, reply: FastifyReply) {}
|
|
45
|
+
function notFoundpreHandlerHandler (request: FastifyRequest, reply: FastifyReply, done: HookHandlerDoneFunction) { done() }
|
|
46
|
+
async function notFoundpreHandlerAsyncHandler (request: FastifyRequest, reply: FastifyReply) {}
|
|
47
|
+
function notFoundpreValidationHandler (request: FastifyRequest, reply: FastifyReply, done: HookHandlerDoneFunction) { done() }
|
|
48
|
+
async function notFoundpreValidationAsyncHandler (request: FastifyRequest, reply: FastifyReply) {}
|
|
49
|
+
|
|
50
|
+
server.setNotFoundHandler(notFoundHandler)
|
|
51
|
+
server.setNotFoundHandler({ preHandler: notFoundpreHandlerHandler }, notFoundHandler)
|
|
52
|
+
server.setNotFoundHandler({ preHandler: notFoundpreHandlerAsyncHandler }, notFoundHandler)
|
|
53
|
+
server.setNotFoundHandler({ preValidation: notFoundpreValidationHandler }, notFoundHandler)
|
|
54
|
+
server.setNotFoundHandler({ preValidation: notFoundpreValidationAsyncHandler }, notFoundHandler)
|
|
55
|
+
server.setNotFoundHandler({ preHandler: notFoundpreHandlerHandler, preValidation: notFoundpreValidationHandler }, notFoundHandler)
|
|
56
|
+
|
|
41
57
|
function invalidErrorHandler (error: number) {}
|
|
42
58
|
expectError(server.setErrorHandler(invalidErrorHandler))
|
|
43
59
|
|
|
@@ -106,3 +122,7 @@ type InitialConfig = Readonly<{
|
|
|
106
122
|
}>
|
|
107
123
|
|
|
108
124
|
expectType<InitialConfig>(fastify().initialConfig)
|
|
125
|
+
|
|
126
|
+
expectType<FastifyContentTypeParser>(server.defaultTextParser)
|
|
127
|
+
|
|
128
|
+
expectType<FastifyContentTypeParser>(server.getDefaultJsonParser('ignore', 'error'))
|
|
@@ -54,3 +54,9 @@ export interface AddContentTypeParser<
|
|
|
54
54
|
* Checks for a type parser of a content type
|
|
55
55
|
*/
|
|
56
56
|
export type hasContentTypeParser = (contentType: string | RegExp) => boolean
|
|
57
|
+
|
|
58
|
+
export type ProtoAction = 'error' | 'remove' | 'ignore'
|
|
59
|
+
|
|
60
|
+
export type ConstructorAction = 'error' | 'remove' | 'ignore'
|
|
61
|
+
|
|
62
|
+
export type getDefaultJsonParser = (onProtoPoisoning: ProtoAction, onConstructorPoisoning: ConstructorAction) => FastifyContentTypeParser
|
package/types/instance.d.ts
CHANGED
|
@@ -8,7 +8,14 @@ import { onRequestHookHandler, preParsingHookHandler, onSendHookHandler, preVali
|
|
|
8
8
|
import { FastifyRequest } from './request'
|
|
9
9
|
import { FastifyReply } from './reply'
|
|
10
10
|
import { FastifyError } from 'fastify-error'
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
AddContentTypeParser,
|
|
13
|
+
hasContentTypeParser,
|
|
14
|
+
getDefaultJsonParser,
|
|
15
|
+
FastifyContentTypeParser,
|
|
16
|
+
ProtoAction,
|
|
17
|
+
ConstructorAction
|
|
18
|
+
} from './content-type-parser'
|
|
12
19
|
|
|
13
20
|
/**
|
|
14
21
|
* Fastify server instance. Returned by the core `fastify()` method.
|
|
@@ -312,10 +319,18 @@ export interface FastifyInstance<
|
|
|
312
319
|
/**
|
|
313
320
|
* Set the 404 handler
|
|
314
321
|
*/
|
|
315
|
-
setNotFoundHandler<RouteGeneric extends RouteGenericInterface = RouteGenericInterface>(
|
|
322
|
+
setNotFoundHandler<RouteGeneric extends RouteGenericInterface = RouteGenericInterface> (
|
|
316
323
|
handler: (request: FastifyRequest<RouteGeneric, RawServer, RawRequest>, reply: FastifyReply<RawServer, RawRequest, RawReply, RouteGeneric>) => void
|
|
317
324
|
): FastifyInstance<RawServer, RawRequest, RawReply, Logger>;
|
|
318
325
|
|
|
326
|
+
setNotFoundHandler<RouteGeneric extends RouteGenericInterface = RouteGenericInterface, ContextConfig extends ContextConfigDefault = ContextConfigDefault> (
|
|
327
|
+
opts: {
|
|
328
|
+
preValidation?: preValidationHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig> | preValidationHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig>[];
|
|
329
|
+
preHandler?: preHandlerHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig> | preHandlerHookHandler<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig>[];
|
|
330
|
+
},
|
|
331
|
+
handler: (request: FastifyRequest<RouteGeneric, RawServer, RawRequest>, reply: FastifyReply<RawServer, RawRequest, RawReply, RouteGeneric>) => void
|
|
332
|
+
): FastifyInstance<RawServer, RawRequest, RawReply, Logger>
|
|
333
|
+
|
|
319
334
|
/**
|
|
320
335
|
* Fastify default error handler
|
|
321
336
|
*/
|
|
@@ -352,6 +367,14 @@ export interface FastifyInstance<
|
|
|
352
367
|
*/
|
|
353
368
|
addContentTypeParser: AddContentTypeParser<RawServer, RawRequest>;
|
|
354
369
|
hasContentTypeParser: hasContentTypeParser;
|
|
370
|
+
/**
|
|
371
|
+
* Fastify default JSON parser
|
|
372
|
+
*/
|
|
373
|
+
getDefaultJsonParser: getDefaultJsonParser;
|
|
374
|
+
/**
|
|
375
|
+
* Fastify default plain text parser
|
|
376
|
+
*/
|
|
377
|
+
defaultTextParser: FastifyContentTypeParser;
|
|
355
378
|
|
|
356
379
|
/**
|
|
357
380
|
* Prints the representation of the internal radix tree used by the router
|
|
@@ -376,8 +399,8 @@ export interface FastifyInstance<
|
|
|
376
399
|
ignoreTrailingSlash?: boolean,
|
|
377
400
|
disableRequestLogging?: boolean,
|
|
378
401
|
maxParamLength?: number,
|
|
379
|
-
onProtoPoisoning?:
|
|
380
|
-
onConstructorPoisoning?:
|
|
402
|
+
onProtoPoisoning?: ProtoAction,
|
|
403
|
+
onConstructorPoisoning?: ConstructorAction,
|
|
381
404
|
pluginTimeout?: number,
|
|
382
405
|
requestIdHeader?: string,
|
|
383
406
|
requestIdLogLabel?: string,
|