fastify 4.0.0-alpha.2 → 4.0.0-alpha.3
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/docs/Guides/Ecosystem.md +9 -0
- package/docs/Reference/Reply.md +50 -0
- package/docs/Reference/Server.md +1 -1
- package/examples/parser.js +12 -2
- package/fastify.js +1 -1
- package/lib/errors.js +8 -0
- package/lib/reply.js +92 -17
- package/lib/server.js +1 -0
- package/lib/symbols.js +1 -0
- package/lib/validation.js +9 -8
- package/package.json +2 -2
- package/test/internals/reply.test.js +50 -23
- package/test/listen.test.js +27 -0
- package/test/reply-trailers.test.js +270 -0
- package/test/types/hooks.test-d.ts +61 -5
- package/test/types/request.test-d.ts +71 -1
- package/test/types/type-provider.test-d.ts +10 -3
- package/types/hooks.d.ts +101 -47
- package/types/instance.d.ts +83 -41
- package/types/request.d.ts +4 -4
- package/types/route.d.ts +46 -29
package/docs/Guides/Ecosystem.md
CHANGED
|
@@ -8,6 +8,9 @@ section.
|
|
|
8
8
|
|
|
9
9
|
#### [Core](#core)
|
|
10
10
|
|
|
11
|
+
- [`aws-lambda-fastify`](https://github.com/fastify/aws-lambda-fastify) allows you to
|
|
12
|
+
easily build serverless web applications/services and RESTful APIs using Fastify
|
|
13
|
+
on top of AWS Lambda and Amazon API Gateway.
|
|
11
14
|
- [`fastify-accepts`](https://github.com/fastify/fastify-accepts) to have
|
|
12
15
|
[accepts](https://www.npmjs.com/package/accepts) in your request object.
|
|
13
16
|
- [`fastify-accepts-serializer`](https://github.com/fastify/fastify-accepts-serializer)
|
|
@@ -295,6 +298,8 @@ section.
|
|
|
295
298
|
An error handling plugin for Fastify that uses enhanced HTTP errors.
|
|
296
299
|
- [`fastify-https-redirect`](https://github.com/tomsvogel/fastify-https-redirect)
|
|
297
300
|
Fastify plugin for auto-redirect from HTTP to HTTPS.
|
|
301
|
+
- [`fatify-impressions`](https://github.com/manju4ever/fastify-impressions) Fastify
|
|
302
|
+
plugin to track impressions of all the routes.
|
|
298
303
|
- [`fastify-influxdb`](https://github.com/alex-ppg/fastify-influxdb) Fastify
|
|
299
304
|
InfluxDB plugin connecting to an InfluxDB instance via the Influx default
|
|
300
305
|
package.
|
|
@@ -334,6 +339,8 @@ section.
|
|
|
334
339
|
- [`fastify-mongoose-driver`](https://github.com/alex-ppg/fastify-mongoose)
|
|
335
340
|
Fastify Mongoose plugin that connects to a MongoDB via the Mongoose plugin
|
|
336
341
|
with support for Models.
|
|
342
|
+
- [`fastify-mqtt`](https://github.com/love-lena/fastify-mqtt) Plugin to share
|
|
343
|
+
[mqtt](https://www.npmjs.com/package/mqtt) client across Fastify.
|
|
337
344
|
- [`fastify-msgpack`](https://github.com/kenriortega/fastify-msgpack) Fastify
|
|
338
345
|
and MessagePack, together at last. Uses @msgpack/msgpack by default.
|
|
339
346
|
- [`fastify-multer`](https://github.com/fox1t/fastify-multer) Multer is a plugin
|
|
@@ -484,6 +491,8 @@ section.
|
|
|
484
491
|
waterline. Decorates Fastify with waterline models.
|
|
485
492
|
- [`fastify-webpack-hmr`](https://github.com/lependu/fastify-webpack-hmr)
|
|
486
493
|
Webpack hot module reloading plugin for Fastify.
|
|
494
|
+
- [`fastify-webpack-hot`](https://github.com/gajus/fastify-webpack-hot)
|
|
495
|
+
Webpack Hot Module Replacement for Fastify.
|
|
487
496
|
- [`fastify-ws`](https://github.com/gj/fastify-ws) WebSocket integration for
|
|
488
497
|
Fastify — with support for WebSocket lifecycle hooks instead of a single
|
|
489
498
|
handler function. Built upon [ws](https://github.com/websockets/ws) and
|
package/docs/Reference/Reply.md
CHANGED
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
- [.getHeaders()](#getheaders)
|
|
14
14
|
- [.removeHeader(key)](#removeheaderkey)
|
|
15
15
|
- [.hasHeader(key)](#hasheaderkey)
|
|
16
|
+
- [.trailer(key, function)](#trailerkey-function)
|
|
17
|
+
- [.hasTrailer(key)](#hastrailerkey)
|
|
18
|
+
- [.removeTrailer(key)](#removetrailerkey)
|
|
16
19
|
- [.redirect([code,] dest)](#redirectcode--dest)
|
|
17
20
|
- [.callNotFound()](#callnotfound)
|
|
18
21
|
- [.getResponseTime()](#getresponsetime)
|
|
@@ -47,6 +50,9 @@ object that exposes the following functions and properties:
|
|
|
47
50
|
- `.getHeaders()` - Gets a shallow copy of all current response headers.
|
|
48
51
|
- `.removeHeader(key)` - Remove the value of a previously set header.
|
|
49
52
|
- `.hasHeader(name)` - Determine if a header has been set.
|
|
53
|
+
- `.trailer(key, function)` - Sets a response trailer.
|
|
54
|
+
- `.hasTrailer(key)` - Determine if a trailer has been set.
|
|
55
|
+
- `.removeTrailer(key)` - Remove the value of a previously set trailer.
|
|
50
56
|
- `.type(value)` - Sets the header `Content-Type`.
|
|
51
57
|
- `.redirect([code,] dest)` - Redirect to the specified url, the status code is
|
|
52
58
|
optional (default to `302`).
|
|
@@ -199,6 +205,49 @@ reply.getHeader('x-foo') // undefined
|
|
|
199
205
|
|
|
200
206
|
Returns a boolean indicating if the specified header has been set.
|
|
201
207
|
|
|
208
|
+
### .trailer(key, function)
|
|
209
|
+
<a id="trailer"></a>
|
|
210
|
+
|
|
211
|
+
Sets a response trailer. Trailer usually used when you want some header that require heavy resources to be sent after the `data`, for example `Server-Timing`, `Etag`. It can ensure the client get the response data as soon as possible.
|
|
212
|
+
|
|
213
|
+
*Note: The header `Transfer-Encoding: chunked` will be added once you use the trailer. It is a hard requipment for using trailer in Node.js.*
|
|
214
|
+
|
|
215
|
+
*Note: Currently, the computation function only supports synchronous function. That means `async-await` and `promise` are not supported.*
|
|
216
|
+
|
|
217
|
+
```js
|
|
218
|
+
reply.trailer('server-timing', function() {
|
|
219
|
+
return 'db;dur=53, app;dur=47.2'
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
const { createHash } = require('crypto')
|
|
223
|
+
// trailer function also recieve two argument
|
|
224
|
+
// @param {object} reply fastify reply
|
|
225
|
+
// @param {string|Buffer|null} payload payload that already sent, note that it will be null when stream is sent
|
|
226
|
+
reply.trailer('content-md5', function(reply, payload) {
|
|
227
|
+
const hash = createHash('md5')
|
|
228
|
+
hash.update(payload)
|
|
229
|
+
return hash.disgest('hex')
|
|
230
|
+
})
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### .hasTrailer(key)
|
|
234
|
+
<a id="hasTrailer"></a>
|
|
235
|
+
|
|
236
|
+
Returns a boolean indicating if the specified trailer has been set.
|
|
237
|
+
|
|
238
|
+
### .removeTrailer(key)
|
|
239
|
+
<a id="removeTrailer"></a>
|
|
240
|
+
|
|
241
|
+
Remove the value of a previously set trailer.
|
|
242
|
+
```js
|
|
243
|
+
reply.trailer('server-timing', function() {
|
|
244
|
+
return 'db;dur=53, app;dur=47.2'
|
|
245
|
+
})
|
|
246
|
+
reply.removeTrailer('server-timing')
|
|
247
|
+
reply.getTrailer('server-timing') // undefined
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
|
|
202
251
|
### .redirect([code ,] dest)
|
|
203
252
|
<a id="redirect"></a>
|
|
204
253
|
|
|
@@ -261,6 +310,7 @@ Sets the content type for the response. This is a shortcut for
|
|
|
261
310
|
```js
|
|
262
311
|
reply.type('text/html')
|
|
263
312
|
```
|
|
313
|
+
If the `Content-Type` has a JSON subtype, and the charset parameter is not set, `utf-8` will be used as the charset by default.
|
|
264
314
|
|
|
265
315
|
### .serializer(func)
|
|
266
316
|
<a id="serializer"></a>
|
package/docs/Reference/Server.md
CHANGED
|
@@ -821,7 +821,7 @@ fastify.ready().then(() => {
|
|
|
821
821
|
#### listen
|
|
822
822
|
<a id="listen"></a>
|
|
823
823
|
|
|
824
|
-
Starts the server and internally waits for the
|
|
824
|
+
Starts the server and internally waits for the `.ready()` event. The
|
|
825
825
|
signature is `.listen([options][, callback])`. Both the `options` object and the
|
|
826
826
|
`callback` parameters follow the [Node.js
|
|
827
827
|
core][https://nodejs.org/api/net.html#serverlistenoptions-callback] parameter
|
package/examples/parser.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const fastify = require('../fastify')({ logger: true })
|
|
4
4
|
const jsonParser = require('fast-json-body')
|
|
5
|
-
const
|
|
5
|
+
const querystring = require('querystring')
|
|
6
6
|
|
|
7
7
|
// Handled by fastify
|
|
8
8
|
// curl -X POST -d '{"hello":"world"}' -H'Content-type: application/json' http://localhost:3000/
|
|
@@ -22,7 +22,7 @@ fastify.addContentTypeParser('application/x-www-form-urlencoded', function (requ
|
|
|
22
22
|
})
|
|
23
23
|
payload.on('end', function () {
|
|
24
24
|
try {
|
|
25
|
-
const parsed =
|
|
25
|
+
const parsed = querystring.parse(body)
|
|
26
26
|
done(null, parsed)
|
|
27
27
|
} catch (e) {
|
|
28
28
|
done(e)
|
|
@@ -31,6 +31,16 @@ fastify.addContentTypeParser('application/x-www-form-urlencoded', function (requ
|
|
|
31
31
|
payload.on('error', done)
|
|
32
32
|
})
|
|
33
33
|
|
|
34
|
+
// curl -X POST -d '{"hello":"world"}' -H'Content-type: application/vnd.custom+json' http://localhost:3000/
|
|
35
|
+
fastify.addContentTypeParser(/^application\/.+\+json$/, { parseAs: 'string' }, fastify.getDefaultJsonParser('error', 'ignore'))
|
|
36
|
+
|
|
37
|
+
// remove default json parser
|
|
38
|
+
// curl -X POST -d '{"hello":"world"}' -H'Content-type: application/json' http://localhost:3000/ is now no longer handled by fastify
|
|
39
|
+
fastify.removeContentTypeParser('application/json')
|
|
40
|
+
|
|
41
|
+
// This call would remove any content type parser
|
|
42
|
+
// fastify.removeAllContentTypeParsers()
|
|
43
|
+
|
|
34
44
|
fastify
|
|
35
45
|
.post('/', function (req, reply) {
|
|
36
46
|
reply.send(req.body)
|
package/fastify.js
CHANGED
package/lib/errors.js
CHANGED
|
@@ -152,6 +152,14 @@ const codes = {
|
|
|
152
152
|
'FST_ERR_BAD_STATUS_CODE',
|
|
153
153
|
'Called reply with an invalid status code: %s'
|
|
154
154
|
),
|
|
155
|
+
FST_ERR_BAD_TRAILER_NAME: createError(
|
|
156
|
+
'FST_ERR_BAD_TRAILER_NAME',
|
|
157
|
+
'Called reply.trailer with an invalid header name: %s'
|
|
158
|
+
),
|
|
159
|
+
FST_ERR_BAD_TRAILER_VALUE: createError(
|
|
160
|
+
'FST_ERR_BAD_TRAILER_VALUE',
|
|
161
|
+
"Called reply.trailer('%s', fn) with an invalid type: %s. Expected a function."
|
|
162
|
+
),
|
|
155
163
|
|
|
156
164
|
/**
|
|
157
165
|
* schemas
|
package/lib/reply.js
CHANGED
|
@@ -12,6 +12,7 @@ const {
|
|
|
12
12
|
kReplySerializerDefault,
|
|
13
13
|
kReplyIsError,
|
|
14
14
|
kReplyHeaders,
|
|
15
|
+
kReplyTrailers,
|
|
15
16
|
kReplyHasStatusCode,
|
|
16
17
|
kReplyIsRunningOnErrorHook,
|
|
17
18
|
kReplyNextErrorHandler,
|
|
@@ -35,7 +36,9 @@ const {
|
|
|
35
36
|
FST_ERR_REP_ALREADY_SENT,
|
|
36
37
|
FST_ERR_REP_SENT_VALUE,
|
|
37
38
|
FST_ERR_SEND_INSIDE_ONERR,
|
|
38
|
-
FST_ERR_BAD_STATUS_CODE
|
|
39
|
+
FST_ERR_BAD_STATUS_CODE,
|
|
40
|
+
FST_ERR_BAD_TRAILER_NAME,
|
|
41
|
+
FST_ERR_BAD_TRAILER_VALUE
|
|
39
42
|
} = require('./errors')
|
|
40
43
|
const warning = require('./warnings')
|
|
41
44
|
|
|
@@ -47,6 +50,7 @@ function Reply (res, request, log) {
|
|
|
47
50
|
this[kReplyIsRunningOnErrorHook] = false
|
|
48
51
|
this.request = request
|
|
49
52
|
this[kReplyHeaders] = {}
|
|
53
|
+
this[kReplyTrailers] = null
|
|
50
54
|
this[kReplyHasStatusCode] = false
|
|
51
55
|
this[kReplyStartTime] = undefined
|
|
52
56
|
this.log = log
|
|
@@ -158,22 +162,14 @@ Reply.prototype.send = function (payload) {
|
|
|
158
162
|
if (hasContentType === false) {
|
|
159
163
|
this[kReplyHeaders]['content-type'] = CONTENT_TYPE.JSON
|
|
160
164
|
} else {
|
|
161
|
-
// If
|
|
165
|
+
// If user doesn't set charset, we will set charset to utf-8
|
|
162
166
|
if (contentType.indexOf('charset') === -1) {
|
|
163
|
-
|
|
164
|
-
if (
|
|
165
|
-
|
|
167
|
+
const customContentType = contentType.trim()
|
|
168
|
+
if (customContentType.endsWith(';')) {
|
|
169
|
+
// custom content-type is ended with ';'
|
|
170
|
+
this[kReplyHeaders]['content-type'] = `${customContentType} charset=utf-8`
|
|
166
171
|
} else {
|
|
167
|
-
|
|
168
|
-
// We extract the custom mimetype part (e.g. 'hal+' from 'application/hal+json')
|
|
169
|
-
const customJsonType = currContentType.substring(
|
|
170
|
-
currContentType.indexOf('/'),
|
|
171
|
-
currContentType.indexOf('json') + 4
|
|
172
|
-
)
|
|
173
|
-
|
|
174
|
-
// We ensure we set the header to the proper JSON content-type if necessary
|
|
175
|
-
// (e.g. 'application/hal+json' instead of 'application/json')
|
|
176
|
-
this[kReplyHeaders]['content-type'] = CONTENT_TYPE.JSON.replace('/json', customJsonType)
|
|
172
|
+
this[kReplyHeaders]['content-type'] = `${customContentType}; charset=utf-8`
|
|
177
173
|
}
|
|
178
174
|
}
|
|
179
175
|
}
|
|
@@ -252,6 +248,47 @@ Reply.prototype.headers = function (headers) {
|
|
|
252
248
|
return this
|
|
253
249
|
}
|
|
254
250
|
|
|
251
|
+
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Trailer#directives
|
|
252
|
+
// https://httpwg.org/specs/rfc7230.html#chunked.trailer.part
|
|
253
|
+
const INVALID_TRAILERS = new Set([
|
|
254
|
+
'transfer-encoding',
|
|
255
|
+
'content-length',
|
|
256
|
+
'host',
|
|
257
|
+
'cache-control',
|
|
258
|
+
'max-forwards',
|
|
259
|
+
'te',
|
|
260
|
+
'authorization',
|
|
261
|
+
'set-cookie',
|
|
262
|
+
'content-encoding',
|
|
263
|
+
'content-type',
|
|
264
|
+
'content-range',
|
|
265
|
+
'trailer'
|
|
266
|
+
])
|
|
267
|
+
|
|
268
|
+
Reply.prototype.trailer = function (key, fn) {
|
|
269
|
+
key = key.toLowerCase()
|
|
270
|
+
if (INVALID_TRAILERS.has(key)) {
|
|
271
|
+
throw new FST_ERR_BAD_TRAILER_NAME(key)
|
|
272
|
+
}
|
|
273
|
+
if (typeof fn !== 'function') {
|
|
274
|
+
throw new FST_ERR_BAD_TRAILER_VALUE(key, typeof fn)
|
|
275
|
+
}
|
|
276
|
+
if (this[kReplyTrailers] === null) this[kReplyTrailers] = {}
|
|
277
|
+
this[kReplyTrailers][key] = fn
|
|
278
|
+
return this
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
Reply.prototype.hasTrailer = function (key) {
|
|
282
|
+
if (this[kReplyTrailers] === null) return false
|
|
283
|
+
return this[kReplyTrailers][key.toLowerCase()] !== undefined
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
Reply.prototype.removeTrailer = function (key) {
|
|
287
|
+
if (this[kReplyTrailers] === null) return this
|
|
288
|
+
this[kReplyTrailers][key.toLowerCase()] = undefined
|
|
289
|
+
return this
|
|
290
|
+
}
|
|
291
|
+
|
|
255
292
|
Reply.prototype.code = function (code) {
|
|
256
293
|
const intValue = parseInt(code)
|
|
257
294
|
if (isNaN(intValue) || intValue < 100 || intValue > 600) {
|
|
@@ -404,6 +441,20 @@ function onSendEnd (reply, payload) {
|
|
|
404
441
|
const req = reply.request
|
|
405
442
|
const statusCode = res.statusCode
|
|
406
443
|
|
|
444
|
+
// we check if we need to update the trailers header and set it
|
|
445
|
+
if (reply[kReplyTrailers] !== null) {
|
|
446
|
+
const trailerHeaders = Object.keys(reply[kReplyTrailers])
|
|
447
|
+
let header = ''
|
|
448
|
+
for (const trailerName of trailerHeaders) {
|
|
449
|
+
if (typeof reply[kReplyTrailers][trailerName] !== 'function') continue
|
|
450
|
+
header += ' '
|
|
451
|
+
header += trailerName
|
|
452
|
+
}
|
|
453
|
+
// it must be chunked for trailer to work
|
|
454
|
+
reply.header('Transfer-Encoding', 'chunked')
|
|
455
|
+
reply.header('Trailer', header.trim())
|
|
456
|
+
}
|
|
457
|
+
|
|
407
458
|
if (payload === undefined || payload === null) {
|
|
408
459
|
// according to https://tools.ietf.org/html/rfc7230#section-3.3.2
|
|
409
460
|
// we cannot send a content-length for 304 and 204, and all status code
|
|
@@ -414,6 +465,7 @@ function onSendEnd (reply, payload) {
|
|
|
414
465
|
}
|
|
415
466
|
|
|
416
467
|
res.writeHead(statusCode, reply[kReplyHeaders])
|
|
468
|
+
sendTrailer(payload, res, reply)
|
|
417
469
|
// avoid ArgumentsAdaptorTrampoline from V8
|
|
418
470
|
res.end(null, null, null)
|
|
419
471
|
return
|
|
@@ -435,9 +487,12 @@ function onSendEnd (reply, payload) {
|
|
|
435
487
|
}
|
|
436
488
|
|
|
437
489
|
res.writeHead(statusCode, reply[kReplyHeaders])
|
|
438
|
-
|
|
490
|
+
// write payload first
|
|
491
|
+
res.write(payload)
|
|
492
|
+
// then send trailers
|
|
493
|
+
sendTrailer(payload, res, reply)
|
|
439
494
|
// avoid ArgumentsAdaptorTrampoline from V8
|
|
440
|
-
res.end(
|
|
495
|
+
res.end(null, null, null)
|
|
441
496
|
}
|
|
442
497
|
|
|
443
498
|
function logStreamError (logger, err, res) {
|
|
@@ -454,6 +509,9 @@ function sendStream (payload, res, reply) {
|
|
|
454
509
|
let sourceOpen = true
|
|
455
510
|
let errorLogged = false
|
|
456
511
|
|
|
512
|
+
// set trailer when stream ended
|
|
513
|
+
sendStreamTrailer(payload, res, reply)
|
|
514
|
+
|
|
457
515
|
eos(payload, { readable: true, writable: false }, function (err) {
|
|
458
516
|
sourceOpen = false
|
|
459
517
|
if (err != null) {
|
|
@@ -502,6 +560,22 @@ function sendStream (payload, res, reply) {
|
|
|
502
560
|
payload.pipe(res)
|
|
503
561
|
}
|
|
504
562
|
|
|
563
|
+
function sendTrailer (payload, res, reply) {
|
|
564
|
+
if (reply[kReplyTrailers] === null) return
|
|
565
|
+
const trailerHeaders = Object.keys(reply[kReplyTrailers])
|
|
566
|
+
const trailers = {}
|
|
567
|
+
for (const trailerName of trailerHeaders) {
|
|
568
|
+
if (typeof reply[kReplyTrailers][trailerName] !== 'function') continue
|
|
569
|
+
trailers[trailerName] = reply[kReplyTrailers][trailerName](reply, payload)
|
|
570
|
+
}
|
|
571
|
+
res.addTrailers(trailers)
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
function sendStreamTrailer (payload, res, reply) {
|
|
575
|
+
if (reply[kReplyTrailers] === null) return
|
|
576
|
+
payload.on('end', () => sendTrailer(null, res, reply))
|
|
577
|
+
}
|
|
578
|
+
|
|
505
579
|
function onErrorHook (reply, error, cb) {
|
|
506
580
|
if (reply.context.onError !== null && !reply[kReplyNextErrorHandler]) {
|
|
507
581
|
reply[kReplyIsRunningOnErrorHook] = true
|
|
@@ -581,6 +655,7 @@ function buildReply (R) {
|
|
|
581
655
|
this[kReplySerializer] = null
|
|
582
656
|
this.request = request
|
|
583
657
|
this[kReplyHeaders] = {}
|
|
658
|
+
this[kReplyTrailers] = null
|
|
584
659
|
this[kReplyStartTime] = undefined
|
|
585
660
|
this[kReplyEndTime] = undefined
|
|
586
661
|
this.log = log
|
package/lib/server.js
CHANGED
package/lib/symbols.js
CHANGED
|
@@ -30,6 +30,7 @@ const keys = {
|
|
|
30
30
|
kReplySerializer: Symbol('fastify.reply.serializer'),
|
|
31
31
|
kReplyIsError: Symbol('fastify.reply.isError'),
|
|
32
32
|
kReplyHeaders: Symbol('fastify.reply.headers'),
|
|
33
|
+
kReplyTrailers: Symbol('fastify.reply.trailers'),
|
|
33
34
|
kReplyHasStatusCode: Symbol('fastify.reply.hasStatusCode'),
|
|
34
35
|
kReplyHijacked: Symbol('fastify.reply.hijacked'),
|
|
35
36
|
kReplyStartTime: Symbol('fastify.reply.startTime'),
|
package/lib/validation.js
CHANGED
|
@@ -27,13 +27,14 @@ function compileSchemasForSerialization (context, compile) {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
function compileSchemasForValidation (context, compile) {
|
|
30
|
-
|
|
30
|
+
const { schema } = context
|
|
31
|
+
if (!schema) {
|
|
31
32
|
return
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
const { method, url } = context.config || {}
|
|
35
36
|
|
|
36
|
-
const headers =
|
|
37
|
+
const headers = schema.headers
|
|
37
38
|
if (headers && Object.getPrototypeOf(headers) !== Object.prototype) {
|
|
38
39
|
// do not mess with non-literals, e.g. Joi schemas
|
|
39
40
|
context[headersSchema] = compile({ schema: headers, method, url, httpPart: 'headers' })
|
|
@@ -54,16 +55,16 @@ function compileSchemasForValidation (context, compile) {
|
|
|
54
55
|
context[headersSchema] = compile({ schema: headersSchemaLowerCase, method, url, httpPart: 'headers' })
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
if (
|
|
58
|
-
context[bodySchema] = compile({ schema:
|
|
58
|
+
if (schema.body) {
|
|
59
|
+
context[bodySchema] = compile({ schema: schema.body, method, url, httpPart: 'body' })
|
|
59
60
|
}
|
|
60
61
|
|
|
61
|
-
if (
|
|
62
|
-
context[querystringSchema] = compile({ schema:
|
|
62
|
+
if (schema.querystring) {
|
|
63
|
+
context[querystringSchema] = compile({ schema: schema.querystring, method, url, httpPart: 'querystring' })
|
|
63
64
|
}
|
|
64
65
|
|
|
65
|
-
if (
|
|
66
|
-
context[paramsSchema] = compile({ schema:
|
|
66
|
+
if (schema.params) {
|
|
67
|
+
context[paramsSchema] = compile({ schema: schema.params, method, url, httpPart: 'params' })
|
|
67
68
|
}
|
|
68
69
|
}
|
|
69
70
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fastify",
|
|
3
|
-
"version": "4.0.0-alpha.
|
|
3
|
+
"version": "4.0.0-alpha.3",
|
|
4
4
|
"description": "Fast and low overhead web framework, for Node.js",
|
|
5
5
|
"main": "fastify.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -161,7 +161,7 @@
|
|
|
161
161
|
"proxyquire": "^2.1.3",
|
|
162
162
|
"pump": "^3.0.0",
|
|
163
163
|
"self-cert": "^2.0.0",
|
|
164
|
-
"send": "^0.
|
|
164
|
+
"send": "^0.18.0",
|
|
165
165
|
"serve-static": "^1.14.1",
|
|
166
166
|
"simple-get": "^4.0.0",
|
|
167
167
|
"snazzy": "^9.0.0",
|