fastify 3.26.0 → 4.0.0-alpha.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 +5 -4
- package/build/build-error-serializer.js +27 -0
- package/build/build-validation.js +49 -35
- package/docs/Guides/Ecosystem.md +2 -1
- package/docs/Guides/Prototype-Poisoning.md +3 -3
- package/docs/Migration-Guide-V4.md +12 -0
- package/docs/Reference/ContentTypeParser.md +8 -1
- package/docs/Reference/Errors.md +51 -6
- package/docs/Reference/Hooks.md +4 -7
- package/docs/Reference/LTS.md +5 -4
- package/docs/Reference/Reply.md +23 -22
- package/docs/Reference/Request.md +1 -3
- package/docs/Reference/Routes.md +17 -10
- package/docs/Reference/Server.md +98 -63
- package/docs/Reference/TypeScript.md +11 -13
- package/docs/Reference/Validation-and-Serialization.md +32 -54
- package/docs/Type-Providers.md +257 -0
- package/examples/hooks.js +1 -1
- package/examples/simple-stream.js +18 -0
- package/fastify.d.ts +36 -22
- package/fastify.js +72 -53
- package/lib/configValidator.js +902 -1023
- package/lib/contentTypeParser.js +6 -16
- package/lib/context.js +36 -10
- package/lib/decorate.js +5 -3
- package/lib/error-handler.js +158 -0
- package/lib/error-serializer.js +257 -0
- package/lib/errors.js +49 -10
- package/lib/fourOhFour.js +31 -20
- package/lib/handleRequest.js +10 -13
- package/lib/hooks.js +14 -9
- package/lib/noop-set.js +10 -0
- package/lib/pluginOverride.js +0 -3
- package/lib/pluginUtils.js +3 -2
- package/lib/reply.js +44 -163
- package/lib/request.js +13 -10
- package/lib/route.js +158 -139
- package/lib/schema-controller.js +3 -3
- package/lib/schemas.js +27 -1
- package/lib/server.js +219 -116
- package/lib/symbols.js +6 -4
- package/lib/validation.js +2 -1
- package/lib/warnings.js +2 -12
- package/lib/wrapThenable.js +4 -11
- package/package.json +40 -45
- package/test/404s.test.js +265 -108
- package/test/500s.test.js +2 -2
- package/test/async-await.test.js +15 -71
- package/test/close.test.js +39 -1
- package/test/content-parser.test.js +32 -0
- package/test/context-config.test.js +56 -4
- package/test/custom-http-server.test.js +14 -7
- package/test/custom-parser-async.test.js +0 -65
- package/test/custom-parser.test.js +54 -121
- package/test/decorator.test.js +1 -3
- package/test/delete.test.js +5 -5
- package/test/encapsulated-error-handler.test.js +50 -0
- package/test/esm/index.test.js +0 -14
- package/test/fastify-instance.test.js +4 -4
- package/test/fluent-schema.test.js +4 -4
- package/test/get.test.js +3 -3
- package/test/helper.js +18 -3
- package/test/hooks-async.test.js +14 -47
- package/test/hooks.on-ready.test.js +9 -4
- package/test/hooks.test.js +58 -99
- package/test/http2/closing.test.js +5 -11
- package/test/http2/unknown-http-method.test.js +3 -9
- package/test/https/custom-https-server.test.js +12 -6
- package/test/inject.test.js +1 -1
- package/test/input-validation.js +2 -2
- package/test/internals/all.test.js +2 -2
- package/test/internals/contentTypeParser.test.js +4 -4
- package/test/internals/handleRequest.test.js +9 -46
- package/test/internals/initialConfig.test.js +33 -12
- package/test/internals/logger.test.js +1 -1
- package/test/internals/reply.test.js +245 -3
- package/test/internals/request.test.js +13 -7
- package/test/internals/server.test.js +88 -0
- package/test/listen.test.js +84 -1
- package/test/logger.test.js +98 -58
- package/test/maxRequestsPerSocket.test.js +8 -6
- package/test/middleware.test.js +2 -25
- package/test/noop-set.test.js +19 -0
- package/test/nullable-validation.test.js +51 -14
- package/test/plugin.test.js +31 -5
- package/test/pretty-print.test.js +22 -10
- package/test/reply-error.test.js +123 -12
- package/test/request-error.test.js +2 -5
- package/test/route-hooks.test.js +17 -17
- package/test/route-prefix.test.js +2 -1
- package/test/route.test.js +216 -20
- package/test/router-options.test.js +1 -1
- package/test/schema-examples.test.js +11 -5
- package/test/schema-feature.test.js +24 -19
- package/test/schema-serialization.test.js +50 -9
- package/test/schema-special-usage.test.js +14 -81
- package/test/schema-validation.test.js +9 -9
- package/test/skip-reply-send.test.js +8 -8
- package/test/stream.test.js +23 -12
- package/test/throw.test.js +8 -5
- package/test/trust-proxy.test.js +1 -1
- package/test/type-provider.test.js +20 -0
- package/test/types/fastify.test-d.ts +12 -18
- package/test/types/hooks.test-d.ts +7 -3
- package/test/types/import.js +2 -0
- package/test/types/import.ts +1 -0
- package/test/types/instance.test-d.ts +61 -15
- package/test/types/logger.test-d.ts +44 -15
- package/test/types/route.test-d.ts +8 -2
- package/test/types/schema.test-d.ts +2 -39
- package/test/types/type-provider.test-d.ts +417 -0
- package/test/validation-error-handling.test.js +9 -9
- package/test/versioned-routes.test.js +29 -17
- package/test/wrapThenable.test.js +7 -6
- package/types/.eslintrc.json +1 -1
- package/types/content-type-parser.d.ts +17 -8
- package/types/hooks.d.ts +107 -60
- package/types/instance.d.ts +137 -105
- package/types/logger.d.ts +18 -104
- package/types/plugin.d.ts +10 -4
- package/types/register.d.ts +1 -1
- package/types/reply.d.ts +16 -11
- package/types/request.d.ts +10 -5
- package/types/route.d.ts +42 -31
- package/types/schema.d.ts +15 -1
- package/types/type-provider.d.ts +99 -0
- package/types/utils.d.ts +1 -1
- package/lib/schema-compilers.js +0 -12
- package/test/emit-warning.test.js +0 -166
package/lib/server.js
CHANGED
|
@@ -1,16 +1,187 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const assert = require('assert')
|
|
4
3
|
const http = require('http')
|
|
5
4
|
const https = require('https')
|
|
5
|
+
const dns = require('dns')
|
|
6
6
|
|
|
7
|
-
const { kState, kOptions } = require('./symbols')
|
|
7
|
+
const { kState, kOptions, kServerBindings } = require('./symbols')
|
|
8
8
|
const { FST_ERR_HTTP2_INVALID_VERSION, FST_ERR_REOPENED_CLOSE_SERVER, FST_ERR_REOPENED_SERVER } = require('./errors')
|
|
9
9
|
|
|
10
|
+
module.exports = createServer
|
|
11
|
+
|
|
10
12
|
function createServer (options, httpHandler) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
const server = getServerInstance(options, httpHandler)
|
|
14
|
+
|
|
15
|
+
return { server, listen }
|
|
16
|
+
|
|
17
|
+
// `this` is the Fastify object
|
|
18
|
+
function listen () {
|
|
19
|
+
const listenOptions = normalizeListenArgs(Array.from(arguments))
|
|
20
|
+
const { cb, host } = listenOptions
|
|
21
|
+
|
|
22
|
+
if (host === 'localhost') {
|
|
23
|
+
listenOptions.cb = (err, address) => {
|
|
24
|
+
if (err) {
|
|
25
|
+
// the server did not start
|
|
26
|
+
cb(err, address)
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
multipleBindings.call(this, server, httpHandler, options, listenOptions, () => {
|
|
31
|
+
this[kState].listening = true
|
|
32
|
+
cb(null, address)
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// https://github.com/nodejs/node/issues/9390
|
|
38
|
+
// If listening to 'localhost', listen to both 127.0.0.1 or ::1 if they are available.
|
|
39
|
+
// If listening to 127.0.0.1, only listen to 127.0.0.1.
|
|
40
|
+
// If listening to ::1, only listen to ::1.
|
|
41
|
+
|
|
42
|
+
if (cb === undefined) {
|
|
43
|
+
const listening = listenPromise.call(this, server, listenOptions)
|
|
44
|
+
if (host === 'localhost') {
|
|
45
|
+
return listening.then(address => {
|
|
46
|
+
return new Promise((resolve, reject) => {
|
|
47
|
+
multipleBindings.call(this, server, httpHandler, options, listenOptions, () => {
|
|
48
|
+
this[kState].listening = true
|
|
49
|
+
resolve(address)
|
|
50
|
+
})
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
return listening
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
this.ready(listenCallback.call(this, server, listenOptions))
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function multipleBindings (mainServer, httpHandler, serverOpts, listenOptions, onListen) {
|
|
62
|
+
// the main server is started, we need to start the secondary servers
|
|
63
|
+
this[kState].listening = false
|
|
64
|
+
|
|
65
|
+
// let's check if we need to bind additional addresses
|
|
66
|
+
dns.lookup(listenOptions.host, { all: true }, (dnsErr, addresses) => {
|
|
67
|
+
if (dnsErr) {
|
|
68
|
+
// not blocking the main server listening
|
|
69
|
+
// this.log.warn('dns.lookup error:', dnsErr)
|
|
70
|
+
onListen()
|
|
71
|
+
return
|
|
72
|
+
}
|
|
13
73
|
|
|
74
|
+
let binding = 0
|
|
75
|
+
let binded = 0
|
|
76
|
+
const primaryAddress = mainServer.address()
|
|
77
|
+
for (const adr of addresses) {
|
|
78
|
+
if (adr.address !== primaryAddress.address) {
|
|
79
|
+
binding++
|
|
80
|
+
const secondaryOpts = Object.assign({}, listenOptions, {
|
|
81
|
+
host: adr.address,
|
|
82
|
+
port: primaryAddress.port,
|
|
83
|
+
cb: (_ignoreErr) => {
|
|
84
|
+
binded++
|
|
85
|
+
|
|
86
|
+
if (!_ignoreErr) {
|
|
87
|
+
this[kServerBindings].push(secondaryServer)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (binded === binding) {
|
|
91
|
+
// regardless of the error, we are done
|
|
92
|
+
onListen()
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
const secondaryServer = getServerInstance(serverOpts, httpHandler)
|
|
98
|
+
const closeSecondary = () => { secondaryServer.close(() => {}) }
|
|
99
|
+
mainServer.on('unref', closeSecondary)
|
|
100
|
+
mainServer.on('close', closeSecondary)
|
|
101
|
+
mainServer.on('error', closeSecondary)
|
|
102
|
+
listenCallback.call(this, secondaryServer, secondaryOpts)()
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// no extra bindings are necessary
|
|
107
|
+
if (binding === 0) {
|
|
108
|
+
onListen()
|
|
109
|
+
return
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// in test files we are using unref so we need to propagate the unref event
|
|
113
|
+
// to the secondary servers. It is valid only when the user is
|
|
114
|
+
// listening on localhost
|
|
115
|
+
const originUnref = mainServer.unref
|
|
116
|
+
/* istanbul ignore next */
|
|
117
|
+
mainServer.unref = function () {
|
|
118
|
+
originUnref.call(mainServer)
|
|
119
|
+
mainServer.emit('unref')
|
|
120
|
+
}
|
|
121
|
+
})
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function listenCallback (server, listenOptions) {
|
|
125
|
+
const wrap = (err) => {
|
|
126
|
+
server.removeListener('error', wrap)
|
|
127
|
+
if (!err) {
|
|
128
|
+
const address = logServerAddress.call(this, server)
|
|
129
|
+
listenOptions.cb(null, address)
|
|
130
|
+
} else {
|
|
131
|
+
this[kState].listening = false
|
|
132
|
+
listenOptions.cb(err, null)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return (err) => {
|
|
137
|
+
if (err != null) return listenOptions.cb(err)
|
|
138
|
+
|
|
139
|
+
if (this[kState].listening && this[kState].closing) {
|
|
140
|
+
return listenOptions.cb(new FST_ERR_REOPENED_CLOSE_SERVER(), null)
|
|
141
|
+
} else if (this[kState].listening) {
|
|
142
|
+
return listenOptions.cb(new FST_ERR_REOPENED_SERVER(), null)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
server.once('error', wrap)
|
|
146
|
+
server.listen(listenOptions, wrap)
|
|
147
|
+
|
|
148
|
+
this[kState].listening = true
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function listenPromise (server, listenOptions) {
|
|
153
|
+
if (this[kState].listening && this[kState].closing) {
|
|
154
|
+
return Promise.reject(new FST_ERR_REOPENED_CLOSE_SERVER())
|
|
155
|
+
} else if (this[kState].listening) {
|
|
156
|
+
return Promise.reject(new FST_ERR_REOPENED_SERVER())
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return this.ready().then(() => {
|
|
160
|
+
let errEventHandler
|
|
161
|
+
const errEvent = new Promise((resolve, reject) => {
|
|
162
|
+
errEventHandler = (err) => {
|
|
163
|
+
this[kState].listening = false
|
|
164
|
+
reject(err)
|
|
165
|
+
}
|
|
166
|
+
server.once('error', errEventHandler)
|
|
167
|
+
})
|
|
168
|
+
const listen = new Promise((resolve, reject) => {
|
|
169
|
+
server.listen(listenOptions, () => {
|
|
170
|
+
server.removeListener('error', errEventHandler)
|
|
171
|
+
resolve(logServerAddress.call(this, server))
|
|
172
|
+
})
|
|
173
|
+
// we set it afterwards because listen can throw
|
|
174
|
+
this[kState].listening = true
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
return Promise.race([
|
|
178
|
+
errEvent, // e.g invalid port range error is always emitted before the server listening
|
|
179
|
+
listen
|
|
180
|
+
])
|
|
181
|
+
})
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function getServerInstance (options, httpHandler) {
|
|
14
185
|
let server = null
|
|
15
186
|
if (options.serverFactory) {
|
|
16
187
|
server = options.serverFactory(httpHandler, options)
|
|
@@ -41,123 +212,57 @@ function createServer (options, httpHandler) {
|
|
|
41
212
|
if (!options.serverFactory) {
|
|
42
213
|
server.setTimeout(options.connectionTimeout)
|
|
43
214
|
}
|
|
215
|
+
return server
|
|
216
|
+
}
|
|
44
217
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const normalizeListenArgs = (args) => {
|
|
50
|
-
if (args.length === 0) {
|
|
51
|
-
return { port: 0, host: 'localhost' }
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const cb = typeof args[args.length - 1] === 'function' ? args.pop() : undefined
|
|
55
|
-
const options = { cb: cb }
|
|
56
|
-
|
|
57
|
-
const firstArg = args[0]
|
|
58
|
-
const argsLength = args.length
|
|
59
|
-
const lastArg = args[argsLength - 1]
|
|
60
|
-
/* Deal with listen (options) || (handle[, backlog]) */
|
|
61
|
-
if (typeof firstArg === 'object' && firstArg !== null) {
|
|
62
|
-
options.backlog = argsLength > 1 ? lastArg : undefined
|
|
63
|
-
Object.assign(options, firstArg)
|
|
64
|
-
} else if (typeof firstArg === 'string' && isNaN(firstArg)) {
|
|
65
|
-
/* Deal with listen (pipe[, backlog]) */
|
|
66
|
-
options.path = firstArg
|
|
67
|
-
options.backlog = argsLength > 1 ? lastArg : undefined
|
|
68
|
-
} else {
|
|
69
|
-
/* Deal with listen ([port[, host[, backlog]]]) */
|
|
70
|
-
options.port = argsLength >= 1 && firstArg ? firstArg : 0
|
|
71
|
-
// This will listen to what localhost is.
|
|
72
|
-
// It can be 127.0.0.1 or ::1, depending on the operating system.
|
|
73
|
-
// Fixes https://github.com/fastify/fastify/issues/1022.
|
|
74
|
-
options.host = argsLength >= 2 && args[1] ? args[1] : 'localhost'
|
|
75
|
-
options.backlog = argsLength >= 3 ? args[2] : undefined
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return options
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const listenOptions = normalizeListenArgs(Array.from(arguments))
|
|
82
|
-
const cb = listenOptions.cb
|
|
83
|
-
|
|
84
|
-
const wrap = err => {
|
|
85
|
-
server.removeListener('error', wrap)
|
|
86
|
-
if (!err) {
|
|
87
|
-
const address = logServerAddress()
|
|
88
|
-
cb(null, address)
|
|
89
|
-
} else {
|
|
90
|
-
this[kState].listening = false
|
|
91
|
-
cb(err, null)
|
|
92
|
-
}
|
|
93
|
-
}
|
|
218
|
+
function normalizeListenArgs (args) {
|
|
219
|
+
if (args.length === 0) {
|
|
220
|
+
return { port: 0, host: 'localhost' }
|
|
221
|
+
}
|
|
94
222
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
return Promise.reject(new FST_ERR_REOPENED_CLOSE_SERVER())
|
|
98
|
-
} else if (this[kState].listening) {
|
|
99
|
-
return Promise.reject(new FST_ERR_REOPENED_SERVER())
|
|
100
|
-
}
|
|
223
|
+
const cb = typeof args[args.length - 1] === 'function' ? args.pop() : undefined
|
|
224
|
+
const options = { cb }
|
|
101
225
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
226
|
+
const firstArg = args[0]
|
|
227
|
+
const argsLength = args.length
|
|
228
|
+
const lastArg = args[argsLength - 1]
|
|
229
|
+
/* Deal with listen (options) || (handle[, backlog]) */
|
|
230
|
+
if (typeof firstArg === 'object' && firstArg !== null) {
|
|
231
|
+
options.backlog = argsLength > 1 ? lastArg : undefined
|
|
232
|
+
Object.assign(options, firstArg)
|
|
233
|
+
} else if (typeof firstArg === 'string' && isNaN(firstArg)) {
|
|
234
|
+
/* Deal with listen (pipe[, backlog]) */
|
|
235
|
+
options.path = firstArg
|
|
236
|
+
options.backlog = argsLength > 1 ? lastArg : undefined
|
|
237
|
+
} else {
|
|
238
|
+
/* Deal with listen ([port[, host[, backlog]]]) */
|
|
239
|
+
options.port = argsLength >= 1 && firstArg ? firstArg : 0
|
|
240
|
+
// This will listen to what localhost is.
|
|
241
|
+
// It can be 127.0.0.1 or ::1, depending on the operating system.
|
|
242
|
+
// Fixes https://github.com/fastify/fastify/issues/1022.
|
|
243
|
+
options.host = argsLength >= 2 && args[1] ? args[1] : 'localhost'
|
|
244
|
+
options.backlog = argsLength >= 3 ? args[2] : undefined
|
|
245
|
+
}
|
|
119
246
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
listen
|
|
123
|
-
])
|
|
124
|
-
})
|
|
125
|
-
}
|
|
247
|
+
return options
|
|
248
|
+
}
|
|
126
249
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
/* istanbul ignore next */
|
|
139
|
-
address = (isUnixSocket ? '' : ('http' + (this[kOptions].https ? 's' : '') + '://')) + address
|
|
140
|
-
this.log.info('Server listening at ' + address)
|
|
141
|
-
return address
|
|
250
|
+
function logServerAddress (server) {
|
|
251
|
+
let address = server.address()
|
|
252
|
+
const isUnixSocket = typeof address === 'string'
|
|
253
|
+
/* istanbul ignore next */
|
|
254
|
+
if (!isUnixSocket) {
|
|
255
|
+
if (address.address.indexOf(':') === -1) {
|
|
256
|
+
address = address.address + ':' + address.port
|
|
257
|
+
} else {
|
|
258
|
+
address = '[' + address.address + ']:' + address.port
|
|
142
259
|
}
|
|
143
|
-
|
|
144
|
-
if (cb === undefined) return listenPromise(listenOptions)
|
|
145
|
-
|
|
146
|
-
this.ready(err => {
|
|
147
|
-
if (err != null) return cb(err)
|
|
148
|
-
|
|
149
|
-
if (this[kState].listening && this[kState].closing) {
|
|
150
|
-
return cb(new FST_ERR_REOPENED_CLOSE_SERVER(), null)
|
|
151
|
-
} else if (this[kState].listening) {
|
|
152
|
-
return cb(new FST_ERR_REOPENED_SERVER(), null)
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
server.once('error', wrap)
|
|
156
|
-
server.listen(listenOptions, wrap)
|
|
157
|
-
|
|
158
|
-
this[kState].listening = true
|
|
159
|
-
})
|
|
160
260
|
}
|
|
261
|
+
/* istanbul ignore next */
|
|
262
|
+
address = (isUnixSocket ? '' : ('http' + (this[kOptions].https ? 's' : '') + '://')) + address
|
|
263
|
+
|
|
264
|
+
this.log.info('Server listening at ' + address)
|
|
265
|
+
return address
|
|
161
266
|
}
|
|
162
267
|
|
|
163
268
|
function http2 () {
|
|
@@ -177,5 +282,3 @@ function sessionTimeout (timeout) {
|
|
|
177
282
|
function close () {
|
|
178
283
|
this.close()
|
|
179
284
|
}
|
|
180
|
-
|
|
181
|
-
module.exports = { createServer }
|
package/lib/symbols.js
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
const keys = {
|
|
4
4
|
kAvvioBoot: Symbol('fastify.avvioBoot'),
|
|
5
5
|
kChildren: Symbol('fastify.children'),
|
|
6
|
+
kServerBindings: Symbol('fastify.serverBindings'),
|
|
6
7
|
kBodyLimit: Symbol('fastify.bodyLimit'),
|
|
7
8
|
kRoutePrefix: Symbol('fastify.routePrefix'),
|
|
8
9
|
kLogLevel: Symbol('fastify.logLevel'),
|
|
9
10
|
kLogSerializers: Symbol('fastify.logSerializers'),
|
|
10
11
|
kHooks: Symbol('fastify.hooks'),
|
|
11
|
-
kHooksDeprecatedPreParsing: Symbol('fastify.hooks.DeprecatedPreParsing'),
|
|
12
12
|
kSchemaController: Symbol('fastify.schemaController'),
|
|
13
13
|
kSchemaHeaders: Symbol('headers-schema'),
|
|
14
14
|
kSchemaParams: Symbol('params-schema'),
|
|
@@ -31,9 +31,9 @@ const keys = {
|
|
|
31
31
|
kReplyIsError: Symbol('fastify.reply.isError'),
|
|
32
32
|
kReplyHeaders: Symbol('fastify.reply.headers'),
|
|
33
33
|
kReplyHasStatusCode: Symbol('fastify.reply.hasStatusCode'),
|
|
34
|
-
|
|
35
|
-
kReplySentOverwritten: Symbol('fastify.reply.sentOverwritten'),
|
|
34
|
+
kReplyHijacked: Symbol('fastify.reply.hijacked'),
|
|
36
35
|
kReplyStartTime: Symbol('fastify.reply.startTime'),
|
|
36
|
+
kReplyNextErrorHandler: Symbol('fastify.reply.nextErrorHandler'),
|
|
37
37
|
kReplyEndTime: Symbol('fastify.reply.endTime'),
|
|
38
38
|
kReplyErrorHandlerCalled: Symbol('fastify.reply.errorHandlerCalled'),
|
|
39
39
|
kReplyIsRunningOnErrorHook: Symbol('fastify.reply.isRunningOnErrorHook'),
|
|
@@ -44,7 +44,9 @@ const keys = {
|
|
|
44
44
|
kPluginNameChain: Symbol('fastify.pluginNameChain'),
|
|
45
45
|
// This symbol is only meant to be used for fastify tests and should not be used for any other purpose
|
|
46
46
|
kTestInternals: Symbol('fastify.testInternals'),
|
|
47
|
-
kErrorHandler: Symbol('fastify.errorHandler')
|
|
47
|
+
kErrorHandler: Symbol('fastify.errorHandler'),
|
|
48
|
+
kHasBeenDecorated: Symbol('fastify.hasBeenDecorated'),
|
|
49
|
+
kKeepAliveConnections: Symbol('fastify.keepAliveConnections')
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
module.exports = keys
|
package/lib/validation.js
CHANGED
|
@@ -68,7 +68,8 @@ function compileSchemasForValidation (context, compile) {
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
function validateParam (validatorFunction, request, paramName) {
|
|
71
|
-
const
|
|
71
|
+
const isUndefined = request[paramName] === undefined
|
|
72
|
+
const ret = validatorFunction && validatorFunction(isUndefined ? null : request[paramName])
|
|
72
73
|
if (ret === false) return validatorFunction.errors
|
|
73
74
|
if (ret && ret.error) return ret.error
|
|
74
75
|
if (ret && ret.value) request[paramName] = ret.value
|
package/lib/warnings.js
CHANGED
|
@@ -4,21 +4,9 @@ const warning = require('process-warning')()
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Deprecation codes:
|
|
7
|
-
* - FSTDEP001
|
|
8
|
-
* - FSTDEP002
|
|
9
|
-
* - FSTDEP003
|
|
10
|
-
* - FSTDEP004
|
|
11
7
|
* - FSTDEP005
|
|
12
8
|
*/
|
|
13
9
|
|
|
14
|
-
warning.create('FastifyDeprecation', 'FSTDEP001', 'You are accessing the Node.js core request object via "request.req", Use "request.raw" instead.')
|
|
15
|
-
|
|
16
|
-
warning.create('FastifyDeprecation', 'FSTDEP002', 'You are accessing the Node.js core response object via "reply.res", Use "reply.raw" instead.')
|
|
17
|
-
|
|
18
|
-
warning.create('FastifyDeprecation', 'FSTDEP003', 'You are using the legacy Content Type Parser function signature. Use the one suggested in the documentation instead.')
|
|
19
|
-
|
|
20
|
-
warning.create('FastifyDeprecation', 'FSTDEP004', 'You are using the legacy preParsing hook signature. Use the one suggested in the documentation instead.')
|
|
21
|
-
|
|
22
10
|
warning.create('FastifyDeprecation', 'FSTDEP005', 'You are accessing the deprecated "request.connection" property. Use "request.socket" instead.')
|
|
23
11
|
|
|
24
12
|
warning.create('FastifyDeprecation', 'FSTDEP006', 'You are decorating Request/Reply with a reference type. This reference is shared amongst all requests. Use onRequest hook instead. Property: %s')
|
|
@@ -29,4 +17,6 @@ warning.create('FastifyDeprecation', 'FSTDEP008', 'You are using route constrain
|
|
|
29
17
|
|
|
30
18
|
warning.create('FastifyDeprecation', 'FSTDEP009', 'You are using a custom route versioning strategy via the server { versioning: "..." } option, use { constraints: { version: "..." } } option instead.')
|
|
31
19
|
|
|
20
|
+
warning.create('FastifyDeprecation', 'FSTDEP010', 'Modifying the "reply.sent" property is deprecated. Use the "reply.hijack()" method instead.')
|
|
21
|
+
|
|
32
22
|
module.exports = warning
|
package/lib/wrapThenable.js
CHANGED
|
@@ -2,40 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
const {
|
|
4
4
|
kReplyIsError,
|
|
5
|
-
|
|
6
|
-
kReplySentOverwritten
|
|
5
|
+
kReplyHijacked
|
|
7
6
|
} = require('./symbols')
|
|
8
7
|
|
|
9
|
-
const { FST_ERR_PROMISE_NOT_FULFILLED } = require('./errors')
|
|
10
|
-
|
|
11
8
|
function wrapThenable (thenable, reply) {
|
|
12
9
|
thenable.then(function (payload) {
|
|
13
|
-
if (reply[
|
|
10
|
+
if (reply[kReplyHijacked] === true) {
|
|
14
11
|
return
|
|
15
12
|
}
|
|
16
13
|
|
|
17
14
|
// this is for async functions that
|
|
18
15
|
// are using reply.send directly
|
|
19
|
-
if (payload !== undefined ||
|
|
16
|
+
if (payload !== undefined || reply.sent === false) {
|
|
20
17
|
// we use a try-catch internally to avoid adding a catch to another
|
|
21
18
|
// promise, increase promise perf by 10%
|
|
22
19
|
try {
|
|
23
20
|
reply.send(payload)
|
|
24
21
|
} catch (err) {
|
|
25
|
-
reply[kReplySent] = false
|
|
26
22
|
reply[kReplyIsError] = true
|
|
27
23
|
reply.send(err)
|
|
28
24
|
}
|
|
29
|
-
} else if (reply[kReplySent] === false) {
|
|
30
|
-
reply.log.error({ err: new FST_ERR_PROMISE_NOT_FULFILLED() }, "Promise may not be fulfilled with 'undefined' when statusCode is not 204")
|
|
31
25
|
}
|
|
32
26
|
}, function (err) {
|
|
33
|
-
if (reply
|
|
27
|
+
if (reply.sent === true) {
|
|
34
28
|
reply.log.error({ err }, 'Promise errored, but reply.sent = true was set')
|
|
35
29
|
return
|
|
36
30
|
}
|
|
37
31
|
|
|
38
|
-
reply[kReplySent] = false
|
|
39
32
|
reply[kReplyIsError] = true
|
|
40
33
|
reply.send(err)
|
|
41
34
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fastify",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0-alpha.1",
|
|
4
4
|
"description": "Fast and low overhead web framework, for Node.js",
|
|
5
5
|
"main": "fastify.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
"license-checker": "license-checker --production --onlyAllow=\"MIT;ISC;BSD-3-Clause;BSD-2-Clause\"",
|
|
13
13
|
"lint": "npm run lint:standard && npm run lint:typescript",
|
|
14
14
|
"lint:fix": "standard --fix",
|
|
15
|
-
"lint:standard": "standard
|
|
15
|
+
"lint:standard": "standard | snazzy",
|
|
16
16
|
"lint:typescript": "eslint -c types/.eslintrc.json types/**/*.d.ts test/types/**/*.test-d.ts",
|
|
17
17
|
"prepublishOnly": "tap --no-check-coverage test/internals/version.test.js",
|
|
18
18
|
"test": "npm run lint && npm run unit && npm run test:typescript",
|
|
19
|
-
"test:ci": "npm run unit -- --cov --coverage-report=lcovonly && npm run test:typescript",
|
|
19
|
+
"test:ci": "npm run unit -- -R terse --cov --coverage-report=lcovonly && npm run test:typescript",
|
|
20
20
|
"test:report": "npm run lint && npm run unit:report && npm run test:typescript",
|
|
21
|
-
"test:typescript": "tsd",
|
|
21
|
+
"test:typescript": "tsc test/types/import.ts && tsd",
|
|
22
22
|
"unit": "tap -J test/*.test.js test/*/*.test.js",
|
|
23
23
|
"unit:junit": "tap-mocha-reporter xunit < out.tap > test/junit-testresults.xml",
|
|
24
24
|
"unit:report": "tap -J test/*.test.js test/*/*.test.js --cov --coverage-report=html --coverage-report=cobertura | tee out.tap"
|
|
@@ -121,82 +121,77 @@
|
|
|
121
121
|
},
|
|
122
122
|
"homepage": "https://www.fastify.io/",
|
|
123
123
|
"devDependencies": {
|
|
124
|
+
"@fastify/ajv-compiler-6": "npm:@fastify/ajv-compiler@^1.0.0",
|
|
124
125
|
"@fastify/ajv-compiler-8": "npm:@fastify/ajv-compiler@^2.0.0",
|
|
125
126
|
"@fastify/pre-commit": "^2.0.1",
|
|
126
|
-
"@
|
|
127
|
-
"@sinonjs/fake-timers": "^8.1.0",
|
|
127
|
+
"@sinonjs/fake-timers": "^9.1.0",
|
|
128
128
|
"@types/node": "^16.0.0",
|
|
129
|
-
"@
|
|
130
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
131
|
-
"@typescript-eslint/parser": "^
|
|
132
|
-
"ajv": "^
|
|
133
|
-
"ajv-errors": "^1.0.1",
|
|
129
|
+
"@sinclair/typebox": "^0.23.1",
|
|
130
|
+
"@typescript-eslint/eslint-plugin": "^5.7.0",
|
|
131
|
+
"@typescript-eslint/parser": "^5.7.0",
|
|
132
|
+
"ajv-errors": "^3.0.0",
|
|
134
133
|
"ajv-formats": "^2.1.1",
|
|
135
|
-
"ajv-i18n": "^
|
|
136
|
-
"ajv-merge-patch": "^
|
|
137
|
-
"
|
|
138
|
-
"branch-comparer": "^1.0.2",
|
|
134
|
+
"ajv-i18n": "^4.2.0",
|
|
135
|
+
"ajv-merge-patch": "^5.0.1",
|
|
136
|
+
"branch-comparer": "^1.1.0",
|
|
139
137
|
"cors": "^2.8.5",
|
|
140
|
-
"coveralls": "^3.1.
|
|
138
|
+
"coveralls": "^3.1.1",
|
|
141
139
|
"dns-prefetch-control": "^0.3.0",
|
|
142
|
-
"eslint": "^
|
|
143
|
-
"eslint-config-standard": "^
|
|
140
|
+
"eslint": "^8.0.1",
|
|
141
|
+
"eslint-config-standard": "^17.0.0-1",
|
|
144
142
|
"eslint-import-resolver-node": "^0.3.2",
|
|
145
|
-
"eslint-plugin-import": "^2.
|
|
146
|
-
"eslint-plugin-
|
|
147
|
-
"eslint-plugin-promise": "^
|
|
148
|
-
"eslint-plugin-standard": "^5.0.0",
|
|
143
|
+
"eslint-plugin-import": "^2.25.4",
|
|
144
|
+
"eslint-plugin-n": "^14.0.0",
|
|
145
|
+
"eslint-plugin-promise": "^6.0.0",
|
|
149
146
|
"fast-json-body": "^1.1.0",
|
|
147
|
+
"fast-json-stringify": "^3.0.0",
|
|
150
148
|
"fastify-plugin": "^3.0.0",
|
|
151
|
-
"fluent-json-schema": "^3.0.
|
|
149
|
+
"fluent-json-schema": "^3.0.1",
|
|
152
150
|
"form-data": "^4.0.0",
|
|
153
151
|
"frameguard": "^4.0.0",
|
|
154
152
|
"h2url": "^0.2.0",
|
|
155
153
|
"helmet": "^5.0.1",
|
|
156
154
|
"hide-powered-by": "^1.1.0",
|
|
157
|
-
"
|
|
158
|
-
"
|
|
159
|
-
"ienoopen": "^1.1.0",
|
|
155
|
+
"joi": "^17.5.0",
|
|
156
|
+
"json-schema-to-ts": "^1.6.4",
|
|
160
157
|
"JSONStream": "^1.3.5",
|
|
161
158
|
"license-checker": "^25.0.1",
|
|
162
159
|
"pem": "^1.14.4",
|
|
163
160
|
"proxyquire": "^2.1.3",
|
|
164
161
|
"pump": "^3.0.0",
|
|
165
|
-
"send": "^0.17.
|
|
162
|
+
"send": "^0.17.2",
|
|
166
163
|
"serve-static": "^1.14.1",
|
|
167
164
|
"simple-get": "^4.0.0",
|
|
168
165
|
"snazzy": "^9.0.0",
|
|
169
166
|
"split2": "^4.1.0",
|
|
170
|
-
"standard": "^
|
|
171
|
-
"tap": "^15.1.
|
|
172
|
-
"
|
|
173
|
-
"
|
|
174
|
-
"
|
|
175
|
-
"typescript": "^4.0.2",
|
|
176
|
-
"undici": "^3.3.5",
|
|
167
|
+
"standard": "^17.0.0-2",
|
|
168
|
+
"tap": "^15.1.6",
|
|
169
|
+
"tsd": "^0.19.1",
|
|
170
|
+
"typescript": "^4.5.4",
|
|
171
|
+
"undici": "^4.11.3",
|
|
177
172
|
"x-xss-protection": "^2.0.0",
|
|
178
|
-
"yup": "^0.32.
|
|
173
|
+
"yup": "^0.32.11"
|
|
179
174
|
},
|
|
180
175
|
"dependencies": {
|
|
181
|
-
"@fastify/ajv-compiler": "^1.0
|
|
182
|
-
"
|
|
183
|
-
"
|
|
184
|
-
"
|
|
185
|
-
"fastify-error": "^0.3.
|
|
176
|
+
"@fastify/ajv-compiler": "^3.1.0",
|
|
177
|
+
"@fastify/fast-json-stringify-compiler": "^1.0.0",
|
|
178
|
+
"abstract-logging": "^2.0.1",
|
|
179
|
+
"avvio": "^8.1.0",
|
|
180
|
+
"fastify-error": "^0.3.1",
|
|
181
|
+
"find-my-way": "^5.1.0",
|
|
182
|
+
"light-my-request": "^4.7.0",
|
|
183
|
+
"pino": "^7.5.1",
|
|
186
184
|
"process-warning": "^1.0.0",
|
|
187
|
-
"find-my-way": "^4.5.0",
|
|
188
|
-
"flatstr": "^1.0.12",
|
|
189
|
-
"light-my-request": "^4.2.0",
|
|
190
|
-
"pino": "^6.13.0",
|
|
191
185
|
"proxy-addr": "^2.0.7",
|
|
192
186
|
"rfdc": "^1.1.4",
|
|
193
187
|
"secure-json-parse": "^2.0.0",
|
|
194
188
|
"semver": "^7.3.2",
|
|
195
|
-
"tiny-lru": "^
|
|
189
|
+
"tiny-lru": "^8.0.1"
|
|
196
190
|
},
|
|
197
191
|
"standard": {
|
|
198
192
|
"ignore": [
|
|
199
193
|
"lib/configValidator.js",
|
|
194
|
+
"lib/error-serializer.js",
|
|
200
195
|
"fastify.d.ts",
|
|
201
196
|
"types/*",
|
|
202
197
|
"test/types/*",
|