fastify 4.6.0 → 4.7.0
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 +19 -8
- package/docs/Guides/Plugins-Guide.md +44 -0
- package/docs/Reference/Reply.md +5 -5
- package/docs/Reference/Request.md +19 -6
- package/docs/Reference/Routes.md +2 -2
- package/docs/Reference/Type-Providers.md +3 -3
- package/fastify.js +1 -1
- package/lib/contentTypeParser.js +10 -9
- package/lib/context.js +27 -3
- package/lib/error-handler.js +7 -3
- package/lib/handleRequest.js +15 -13
- package/lib/reply.js +42 -34
- package/lib/request.js +36 -18
- package/lib/route.js +16 -10
- package/lib/schema-controller.js +7 -1
- package/lib/server.js +2 -2
- package/lib/symbols.js +2 -0
- package/lib/validation.js +4 -3
- package/lib/warnings.js +2 -0
- package/package.json +26 -26
- package/test/404s.test.js +19 -1
- package/test/context-config.test.js +2 -1
- package/test/handler-context.test.js +12 -30
- package/test/internals/contentTypeParser.test.js +3 -3
- package/test/internals/handleRequest.test.js +4 -3
- package/test/internals/reply-serialize.test.js +9 -9
- package/test/internals/reply.test.js +10 -9
- package/test/internals/request-validate.test.js +97 -9
- package/test/internals/request.test.js +57 -3
- package/test/internals/validation.test.js +15 -0
- package/test/plugin.test.js +1 -1
- package/test/reply-code.test.js +59 -0
- package/test/route.test.js +29 -0
- package/test/router-options.test.js +33 -66
- package/test/schema-feature.test.js +25 -0
- package/test/schema-validation.test.js +19 -0
- package/test/search.test.js +169 -30
- package/test/server.test.js +54 -0
- package/types/request.d.ts +9 -3
package/docs/Guides/Ecosystem.md
CHANGED
|
@@ -80,6 +80,8 @@ section.
|
|
|
80
80
|
[Next](https://github.com/zeit/next.js/).
|
|
81
81
|
- [`@fastify/oauth2`](https://github.com/fastify/fastify-oauth2) Wrap around
|
|
82
82
|
[`simple-oauth2`](https://github.com/lelylan/simple-oauth2).
|
|
83
|
+
- [`@fastify/one-line-logger`](https://github.com/fastify/one-line-logger) Formats
|
|
84
|
+
Fastify's logs into a nice one-line message.
|
|
83
85
|
- [`@fastify/postgres`](https://github.com/fastify/fastify-postgres) Fastify
|
|
84
86
|
PostgreSQL connection plugin, with this you can share the same PostgreSQL
|
|
85
87
|
connection pool in every part of your server.
|
|
@@ -119,10 +121,10 @@ section.
|
|
|
119
121
|
- [`@fastify/type-provider-json-schema-to-ts`](https://github.com/fastify/fastify-type-provider-json-schema-to-ts)
|
|
120
122
|
Fastify
|
|
121
123
|
[type provider](https://www.fastify.io/docs/latest/Reference/Type-Providers/)
|
|
122
|
-
for [json-schema-to-ts](https://github.com/ThomasAribart/json-schema-to-ts).
|
|
124
|
+
for [json-schema-to-ts](https://github.com/ThomasAribart/json-schema-to-ts).
|
|
123
125
|
- [`@fastify/type-provider-typebox`](https://github.com/fastify/fastify-type-provider-typebox)
|
|
124
126
|
Fastify
|
|
125
|
-
[type provider](https://www.fastify.io/docs/latest/Reference/Type-Providers/)
|
|
127
|
+
[type provider](https://www.fastify.io/docs/latest/Reference/Type-Providers/)
|
|
126
128
|
for [Typebox](https://github.com/sinclairzx81/typebox).
|
|
127
129
|
- [`@fastify/under-pressure`](https://github.com/fastify/under-pressure) Measure
|
|
128
130
|
process load with automatic handling of _"Service Unavailable"_ plugin for
|
|
@@ -167,7 +169,7 @@ section.
|
|
|
167
169
|
Sentry errors handler that just works! Install, add your DSN and you're good
|
|
168
170
|
to go!
|
|
169
171
|
- [`@mateonunez/fastify-lyra`](https://github.com/mateonunez/fastify-lyra)
|
|
170
|
-
A plugin to implement [Lyra](https://github.com/nearform/lyra) search engine
|
|
172
|
+
A plugin to implement [Lyra](https://github.com/nearform/lyra) search engine
|
|
171
173
|
on Fastify
|
|
172
174
|
- [`@mgcrea/fastify-graceful-exit`](https://github.com/mgcrea/fastify-graceful-exit)
|
|
173
175
|
A plugin to close the server gracefully
|
|
@@ -191,7 +193,7 @@ section.
|
|
|
191
193
|
- [`cls-rtracer`](https://github.com/puzpuzpuz/cls-rtracer) Fastify middleware
|
|
192
194
|
for CLS-based request ID generation. An out-of-the-box solution for adding
|
|
193
195
|
request IDs into your logs.
|
|
194
|
-
- [`electron-server`](https://github.com/anonrig/electron-server) A plugin for
|
|
196
|
+
- [`electron-server`](https://github.com/anonrig/electron-server) A plugin for
|
|
195
197
|
using Fastify without the need of consuming a port on Electron apps.
|
|
196
198
|
- [`fast-water`](https://github.com/tswayne/fast-water) A Fastify plugin for
|
|
197
199
|
waterline. Decorates Fastify with waterline models.
|
|
@@ -446,7 +448,7 @@ section.
|
|
|
446
448
|
OrientDB connection plugin, with which you can share the OrientDB connection
|
|
447
449
|
across every part of your server.
|
|
448
450
|
- [`fastify-osm`](https://github.com/gzileni/fastify-osm) Fastify
|
|
449
|
-
OSM plugin to run overpass queries by OpenStreetMap.
|
|
451
|
+
OSM plugin to run overpass queries by OpenStreetMap.
|
|
450
452
|
- [`fastify-peekaboo`](https://github.com/simone-sanfratello/fastify-peekaboo)
|
|
451
453
|
Fastify plugin for memoize responses by expressive settings.
|
|
452
454
|
- [`fastify-piscina`](https://github.com/piscinajs/fastify-piscina) A worker
|
|
@@ -471,6 +473,9 @@ section.
|
|
|
471
473
|
[qs](https://github.com/ljharb/qs).
|
|
472
474
|
- [`fastify-racing`](https://github.com/metcoder95/fastify-racing) Fastify's
|
|
473
475
|
plugin that adds support to handle an aborted request asynchronous.
|
|
476
|
+
- [`fastify-ravendb`](https://github.com/nearform/fastify-ravendb) RavenDB
|
|
477
|
+
connection plugin. It exposes the same `DocumentStore` (or multiple ones)
|
|
478
|
+
across the whole Fastify application.
|
|
474
479
|
- [`fastify-raw-body`](https://github.com/Eomm/fastify-raw-body) Add the
|
|
475
480
|
`request.rawBody` field.
|
|
476
481
|
- [`fastify-rbac`](https://gitlab.com/m03geek/fastify-rbac) Fastify role-based
|
|
@@ -496,7 +501,9 @@ section.
|
|
|
496
501
|
- [`fastify-rob-config`](https://github.com/jeromemacias/fastify-rob-config)
|
|
497
502
|
Fastify Rob-Config integration.
|
|
498
503
|
- [`fastify-route-group`](https://github.com/TakNePoidet/fastify-route-group)
|
|
499
|
-
Convenient grouping and inheritance of routes
|
|
504
|
+
Convenient grouping and inheritance of routes.
|
|
505
|
+
- [`fastify-s3-buckets`](https://github.com/kibertoad/fastify-s3-buckets)
|
|
506
|
+
Ensure the existence of defined S3 buckets on the application startup.
|
|
500
507
|
- [`fastify-schema-constraint`](https://github.com/Eomm/fastify-schema-constraint)
|
|
501
508
|
Choose the JSON schema to use based on request parameters.
|
|
502
509
|
- [`fastify-schema-to-typescript`](https://github.com/thomasthiebaud/fastify-schema-to-typescript)
|
|
@@ -512,11 +519,15 @@ section.
|
|
|
512
519
|
`fastify-caching`.
|
|
513
520
|
- [`fastify-slonik`](https://github.com/Unbuttun/fastify-slonik) Fastify Slonik
|
|
514
521
|
plugin, with this you can use slonik in every part of your server.
|
|
522
|
+
- [`fastify-slow-down`](https://github.com/nearform/fastify-slow-down) A plugin
|
|
523
|
+
to delay the response from the server.
|
|
515
524
|
- [`fastify-socket.io`](https://github.com/alemagio/fastify-socket.io) a
|
|
516
525
|
Socket.io plugin for Fastify.
|
|
517
526
|
- [`fastify-split-validator`](https://github.com/MetCoder95/fastify-split-validator)
|
|
518
527
|
Small plugin to allow you use multiple validators in one route based on each
|
|
519
528
|
HTTP part of the request.
|
|
529
|
+
- [`fastify-sqlite`](https://github.com/Eomm/fastify-sqlite) connects your
|
|
530
|
+
application to a sqlite3 database.
|
|
520
531
|
- [`fastify-sse`](https://github.com/lolo32/fastify-sse) to provide Server-Sent
|
|
521
532
|
Events with `reply.sse( … )` to Fastify.
|
|
522
533
|
- [`fastify-sse-v2`](https://github.com/nodefactoryio/fastify-sse-v2) to provide
|
|
@@ -541,8 +552,8 @@ section.
|
|
|
541
552
|
- [`fastify-twitch-ebs-tools`](https://github.com/lukemnet/fastify-twitch-ebs-tools)
|
|
542
553
|
Useful functions for Twitch Extension Backend Services (EBS).
|
|
543
554
|
- [`fastify-type-provider-zod`](https://github.com/turkerdev/fastify-type-provider-zod)
|
|
544
|
-
Fastify
|
|
545
|
-
[type provider](https://www.fastify.io/docs/latest/Reference/Type-Providers/)
|
|
555
|
+
Fastify
|
|
556
|
+
[type provider](https://www.fastify.io/docs/latest/Reference/Type-Providers/)
|
|
546
557
|
for [zod](https://github.com/colinhacks/zod).
|
|
547
558
|
- [`fastify-typeorm-plugin`](https://github.com/inthepocket/fastify-typeorm-plugin)
|
|
548
559
|
Fastify plugin to work with TypeORM.
|
|
@@ -308,6 +308,50 @@ fastify.get('/plugin2', (request, reply) => {
|
|
|
308
308
|
```
|
|
309
309
|
Now your hook will run just for the first route!
|
|
310
310
|
|
|
311
|
+
An alternative approach is to make use of the [onRoute hook](../Reference/Hooks.md#onroute)
|
|
312
|
+
to customize application routes dynamically from inside the plugin. Every time
|
|
313
|
+
a new route is registered, you can read and modify the route options. For example,
|
|
314
|
+
based on a [route config option](../Reference/Routes.md#routes-options):
|
|
315
|
+
|
|
316
|
+
```js
|
|
317
|
+
fastify.register((instance, opts, done) => {
|
|
318
|
+
instance.decorate('util', (request, key, value) => { request[key] = value })
|
|
319
|
+
|
|
320
|
+
function handler(request, reply, done) {
|
|
321
|
+
instance.util(request, 'timestamp', new Date())
|
|
322
|
+
done()
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
instance.addHook('onRoute', (routeOptions) => {
|
|
326
|
+
if (routeOptions.config && routeOptions.config.useUtil === true) {
|
|
327
|
+
// set or add our handler to the route preHandler hook
|
|
328
|
+
if (!routeOptions.preHandler) {
|
|
329
|
+
routeOptions.preHandler = [handler]
|
|
330
|
+
return
|
|
331
|
+
}
|
|
332
|
+
if (Array.isArray(routeOptions.preHandler)) {
|
|
333
|
+
routeOptions.preHandler.push(handler)
|
|
334
|
+
return
|
|
335
|
+
}
|
|
336
|
+
routeOptions.preHandler = [routeOptions.preHandler, handler]
|
|
337
|
+
}
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
fastify.get('/plugin1', {config: {useUtil: true}}, (request, reply) => {
|
|
341
|
+
reply.send(request)
|
|
342
|
+
})
|
|
343
|
+
|
|
344
|
+
fastify.get('/plugin2', (request, reply) => {
|
|
345
|
+
reply.send(request)
|
|
346
|
+
})
|
|
347
|
+
|
|
348
|
+
done()
|
|
349
|
+
})
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
This variant becomes extremely useful if you plan to distribute your plugin, as
|
|
353
|
+
described in the next section.
|
|
354
|
+
|
|
311
355
|
As you probably noticed by now, `request` and `reply` are not the standard
|
|
312
356
|
Nodejs *request* and *response* objects, but Fastify's objects.
|
|
313
357
|
|
package/docs/Reference/Reply.md
CHANGED
|
@@ -7,22 +7,22 @@
|
|
|
7
7
|
- [.statusCode](#statuscode)
|
|
8
8
|
- [.server](#server)
|
|
9
9
|
- [.header(key, value)](#headerkey-value)
|
|
10
|
-
- [set-cookie](#set-cookie)
|
|
11
10
|
- [.headers(object)](#headersobject)
|
|
12
11
|
- [.getHeader(key)](#getheaderkey)
|
|
13
12
|
- [.getHeaders()](#getheaders)
|
|
13
|
+
- [set-cookie](#set-cookie)
|
|
14
14
|
- [.removeHeader(key)](#removeheaderkey)
|
|
15
15
|
- [.hasHeader(key)](#hasheaderkey)
|
|
16
16
|
- [.trailer(key, function)](#trailerkey-function)
|
|
17
17
|
- [.hasTrailer(key)](#hastrailerkey)
|
|
18
18
|
- [.removeTrailer(key)](#removetrailerkey)
|
|
19
|
-
- [.redirect([code,] dest)](#redirectcode--dest)
|
|
19
|
+
- [.redirect([code ,] dest)](#redirectcode--dest)
|
|
20
20
|
- [.callNotFound()](#callnotfound)
|
|
21
21
|
- [.getResponseTime()](#getresponsetime)
|
|
22
22
|
- [.type(contentType)](#typecontenttype)
|
|
23
|
-
- [.getSerializationFunction(schema | httpStatus)](#
|
|
24
|
-
- [.compileSerializationSchema(schema, httpStatus)](#
|
|
25
|
-
- [.serializeInput(data, [schema | httpStatus], [httpStatus])](#
|
|
23
|
+
- [.getSerializationFunction(schema | httpStatus)](#getserializationfunctionschema--httpstatus)
|
|
24
|
+
- [.compileSerializationSchema(schema, httpStatus)](#compileserializationschemaschema-httpstatus)
|
|
25
|
+
- [.serializeInput(data, [schema | httpStatus], [httpStatus])](#serializeinputdata-schema--httpstatus-httpstatus)
|
|
26
26
|
- [.serializer(func)](#serializerfunc)
|
|
27
27
|
- [.raw](#raw)
|
|
28
28
|
- [.sent](#sent)
|
|
@@ -35,6 +35,13 @@ Request is a core Fastify object containing the following fields:
|
|
|
35
35
|
- `connection` - Deprecated, use `socket` instead. The underlying connection of
|
|
36
36
|
the incoming request.
|
|
37
37
|
- `socket` - the underlying connection of the incoming request
|
|
38
|
+
- `context` - A Fastify internal object. You should not use it directly or
|
|
39
|
+
modify it. It is useful to access one special key:
|
|
40
|
+
- `context.config` - The route [`config`](./Routes.md#routes-config) object.
|
|
41
|
+
- `routeSchema` - the scheme definition set for the router that is
|
|
42
|
+
handling the request
|
|
43
|
+
- `routeConfig` - The route [`config`](./Routes.md#routes-config)
|
|
44
|
+
object.
|
|
38
45
|
- [.getValidationFunction(schema | httpPart)](#getvalidationfunction) -
|
|
39
46
|
Returns a validation function for the specified schema or http part,
|
|
40
47
|
if any of either are set or cached.
|
|
@@ -48,9 +55,6 @@ Request is a core Fastify object containing the following fields:
|
|
|
48
55
|
schema and returns the serialized payload. If the optional
|
|
49
56
|
`httpPart` is provided, the function will use the serializer
|
|
50
57
|
function given for that HTTP Status Code. Defaults to `null`.
|
|
51
|
-
- `context` - A Fastify internal object. You should not use it directly or
|
|
52
|
-
modify it. It is useful to access one special key:
|
|
53
|
-
- `context.config` - The route [`config`](./Routes.md#routes-config) object.
|
|
54
58
|
|
|
55
59
|
### Headers
|
|
56
60
|
|
|
@@ -98,6 +102,9 @@ it will return a `validation` function that can be used to
|
|
|
98
102
|
validate diverse inputs. It returns `undefined` if no
|
|
99
103
|
serialization function was found using either of the provided inputs.
|
|
100
104
|
|
|
105
|
+
This function has property errors. Errors encountered during the last validation
|
|
106
|
+
are assigned to errors
|
|
107
|
+
|
|
101
108
|
```js
|
|
102
109
|
const validate = request
|
|
103
110
|
.getValidationFunction({
|
|
@@ -108,13 +115,15 @@ const validate = request
|
|
|
108
115
|
}
|
|
109
116
|
}
|
|
110
117
|
})
|
|
111
|
-
validate({ foo: 'bar' }) // true
|
|
118
|
+
console.log(validate({ foo: 'bar' })) // true
|
|
119
|
+
console.log(validate.errors) // null
|
|
112
120
|
|
|
113
121
|
// or
|
|
114
122
|
|
|
115
123
|
const validate = request
|
|
116
124
|
.getValidationFunction('body')
|
|
117
|
-
validate({ foo: 0.5 }) // false
|
|
125
|
+
console.log(validate({ foo: 0.5 })) // false
|
|
126
|
+
console.log(validate.errors) // validation errors
|
|
118
127
|
```
|
|
119
128
|
|
|
120
129
|
See [.compilaValidationSchema(schema, [httpStatus])](#compilevalidationschema)
|
|
@@ -133,6 +142,8 @@ The optional parameter `httpPart`, if provided, is forwarded directly
|
|
|
133
142
|
the `ValidationCompiler`, so it can be used to compile the validation
|
|
134
143
|
function if a custom `ValidationCompiler` is provided for the route.
|
|
135
144
|
|
|
145
|
+
This function has property errors. Errors encountered during the last validation
|
|
146
|
+
are assigned to errors
|
|
136
147
|
|
|
137
148
|
```js
|
|
138
149
|
const validate = request
|
|
@@ -145,6 +156,7 @@ const validate = request
|
|
|
145
156
|
}
|
|
146
157
|
})
|
|
147
158
|
console.log(validate({ foo: 'bar' })) // true
|
|
159
|
+
console.log(validate.errors) // null
|
|
148
160
|
|
|
149
161
|
// or
|
|
150
162
|
|
|
@@ -158,6 +170,7 @@ const validate = request
|
|
|
158
170
|
}
|
|
159
171
|
}, 200)
|
|
160
172
|
console.log(validate({ hello: 'world' })) // false
|
|
173
|
+
console.log(validate.errors) // validation errors
|
|
161
174
|
```
|
|
162
175
|
|
|
163
176
|
Note that you should be careful when using this function, as it will cache
|
|
@@ -247,4 +260,4 @@ request
|
|
|
247
260
|
```
|
|
248
261
|
|
|
249
262
|
See [.compileValidationSchema(schema, [httpStatus])](#compileValidationSchema)
|
|
250
|
-
for more information on how to compile validation schemas.
|
|
263
|
+
for more information on how to compile validation schemas.
|
package/docs/Reference/Routes.md
CHANGED
|
@@ -41,8 +41,8 @@ fastify.route(options)
|
|
|
41
41
|
need to be in [JSON Schema](https://json-schema.org/) format, check
|
|
42
42
|
[here](./Validation-and-Serialization.md) for more info.
|
|
43
43
|
|
|
44
|
-
* `body`: validates the body of the request if it is a POST, PUT,
|
|
45
|
-
method.
|
|
44
|
+
* `body`: validates the body of the request if it is a POST, PUT, PATCH,
|
|
45
|
+
TRACE, or SEARCH method.
|
|
46
46
|
* `querystring` or `query`: validates the querystring. This can be a complete
|
|
47
47
|
JSON Schema object, with the property `type` of `object` and `properties`
|
|
48
48
|
object of parameters, or simply the values of what would be contained in the
|
|
@@ -148,7 +148,7 @@ fastify.register(pluginWithTypebox)
|
|
|
148
148
|
|
|
149
149
|
It's also important to mention that once the types don't propagate globally,
|
|
150
150
|
_currently_ is not possible to avoid multiple registrations on routes when
|
|
151
|
-
dealing with several scopes, see
|
|
151
|
+
dealing with several scopes, see below:
|
|
152
152
|
|
|
153
153
|
```ts
|
|
154
154
|
import Fastify from 'fastify'
|
|
@@ -218,7 +218,7 @@ server.listen({ port: 3000 })
|
|
|
218
218
|
import { Type } from '@sinclair/typebox'
|
|
219
219
|
import {
|
|
220
220
|
FastifyInstance,
|
|
221
|
-
|
|
221
|
+
FastifyBaseLogger,
|
|
222
222
|
RawReplyDefaultExpression,
|
|
223
223
|
RawRequestDefaultExpression,
|
|
224
224
|
RawServerDefault
|
|
@@ -229,7 +229,7 @@ type FastifyTypebox = FastifyInstance<
|
|
|
229
229
|
RawServerDefault,
|
|
230
230
|
RawRequestDefaultExpression<RawServerDefault>,
|
|
231
231
|
RawReplyDefaultExpression<RawServerDefault>,
|
|
232
|
-
|
|
232
|
+
FastifyBaseLogger,
|
|
233
233
|
TypeBoxTypeProvider
|
|
234
234
|
>;
|
|
235
235
|
|
package/fastify.js
CHANGED
package/lib/contentTypeParser.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { AsyncResource } = require('async_hooks')
|
|
4
|
-
|
|
5
|
-
// Needed to handle Webpack and faux modules
|
|
6
|
-
// See https://github.com/fastify/fastify/issues/2356
|
|
7
|
-
// and https://github.com/fastify/fastify/discussions/2907.
|
|
8
|
-
lru = typeof lru === 'function' ? lru : lru.default
|
|
4
|
+
const lru = require('tiny-lru').lru
|
|
9
5
|
|
|
10
6
|
const secureJson = require('secure-json-parse')
|
|
11
7
|
const {
|
|
@@ -15,7 +11,8 @@ const {
|
|
|
15
11
|
kRequestPayloadStream,
|
|
16
12
|
kState,
|
|
17
13
|
kTestInternals,
|
|
18
|
-
kReplyIsError
|
|
14
|
+
kReplyIsError,
|
|
15
|
+
kRouteContext
|
|
19
16
|
} = require('./symbols')
|
|
20
17
|
|
|
21
18
|
const {
|
|
@@ -149,12 +146,16 @@ ContentTypeParser.prototype.run = function (contentType, handler, request, reply
|
|
|
149
146
|
const resource = new AsyncResource('content-type-parser:run', request)
|
|
150
147
|
|
|
151
148
|
if (parser === undefined) {
|
|
152
|
-
|
|
149
|
+
if (request.is404) {
|
|
150
|
+
handler(request, reply)
|
|
151
|
+
} else {
|
|
152
|
+
reply.send(new FST_ERR_CTP_INVALID_MEDIA_TYPE(contentType || undefined))
|
|
153
|
+
}
|
|
153
154
|
} else if (parser.asString === true || parser.asBuffer === true) {
|
|
154
155
|
rawBody(
|
|
155
156
|
request,
|
|
156
157
|
reply,
|
|
157
|
-
reply.
|
|
158
|
+
reply[kRouteContext]._parserOptions,
|
|
158
159
|
parser,
|
|
159
160
|
done
|
|
160
161
|
)
|
|
@@ -185,7 +186,7 @@ function rawBody (request, reply, options, parser, done) {
|
|
|
185
186
|
const limit = options.limit === null ? parser.bodyLimit : options.limit
|
|
186
187
|
const contentLength = request.headers['content-length'] === undefined
|
|
187
188
|
? NaN
|
|
188
|
-
: Number
|
|
189
|
+
: Number(request.headers['content-length'])
|
|
189
190
|
|
|
190
191
|
if (contentLength > limit) {
|
|
191
192
|
reply.send(new FST_ERR_CTP_BODY_TOO_LARGE())
|
package/lib/context.js
CHANGED
|
@@ -12,10 +12,11 @@ const {
|
|
|
12
12
|
kContentTypeParser,
|
|
13
13
|
kRouteByFastify,
|
|
14
14
|
kRequestValidateWeakMap,
|
|
15
|
-
kReplySerializeWeakMap
|
|
15
|
+
kReplySerializeWeakMap,
|
|
16
|
+
kPublicRouteContext
|
|
16
17
|
} = require('./symbols.js')
|
|
17
18
|
|
|
18
|
-
//
|
|
19
|
+
// Object that holds the context of every request
|
|
19
20
|
// Every route holds an instance of this object.
|
|
20
21
|
function Context ({
|
|
21
22
|
schema,
|
|
@@ -56,7 +57,10 @@ function Context ({
|
|
|
56
57
|
this[kFourOhFourContext] = null
|
|
57
58
|
this.attachValidation = attachValidation
|
|
58
59
|
this[kReplySerializerDefault] = replySerializer
|
|
59
|
-
this.schemaErrorFormatter =
|
|
60
|
+
this.schemaErrorFormatter =
|
|
61
|
+
schemaErrorFormatter ||
|
|
62
|
+
server[kSchemaErrorFormatter] ||
|
|
63
|
+
defaultSchemaErrorFormatter
|
|
60
64
|
this[kRouteByFastify] = isFastify
|
|
61
65
|
|
|
62
66
|
this[kRequestValidateWeakMap] = null
|
|
@@ -64,9 +68,29 @@ function Context ({
|
|
|
64
68
|
this.validatorCompiler = validatorCompiler || null
|
|
65
69
|
this.serializerCompiler = serializerCompiler || null
|
|
66
70
|
|
|
71
|
+
// Route + Userland configurations for the route
|
|
72
|
+
this[kPublicRouteContext] = getPublicRouteContext(this)
|
|
73
|
+
|
|
67
74
|
this.server = server
|
|
68
75
|
}
|
|
69
76
|
|
|
77
|
+
function getPublicRouteContext (context) {
|
|
78
|
+
return Object.create(null, {
|
|
79
|
+
schema: {
|
|
80
|
+
enumerable: true,
|
|
81
|
+
get () {
|
|
82
|
+
return context.schema
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
config: {
|
|
86
|
+
enumerable: true,
|
|
87
|
+
get () {
|
|
88
|
+
return context.config
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
|
|
70
94
|
function defaultSchemaErrorFormatter (errors, dataVar) {
|
|
71
95
|
let text = ''
|
|
72
96
|
const separator = ', '
|
package/lib/error-handler.js
CHANGED
|
@@ -3,7 +3,11 @@
|
|
|
3
3
|
const statusCodes = require('http').STATUS_CODES
|
|
4
4
|
const wrapThenable = require('./wrapThenable')
|
|
5
5
|
const {
|
|
6
|
-
kReplyHeaders,
|
|
6
|
+
kReplyHeaders,
|
|
7
|
+
kReplyNextErrorHandler,
|
|
8
|
+
kReplyIsRunningOnErrorHook,
|
|
9
|
+
kReplyHasStatusCode,
|
|
10
|
+
kRouteContext
|
|
7
11
|
} = require('./symbols.js')
|
|
8
12
|
|
|
9
13
|
const {
|
|
@@ -24,7 +28,7 @@ const rootErrorHandler = {
|
|
|
24
28
|
function handleError (reply, error, cb) {
|
|
25
29
|
reply[kReplyIsRunningOnErrorHook] = false
|
|
26
30
|
|
|
27
|
-
const context = reply
|
|
31
|
+
const context = reply[kRouteContext]
|
|
28
32
|
if (reply[kReplyNextErrorHandler] === false) {
|
|
29
33
|
fallbackErrorHandler(error, reply, function (reply, payload) {
|
|
30
34
|
try {
|
|
@@ -90,7 +94,7 @@ function fallbackErrorHandler (error, reply, cb) {
|
|
|
90
94
|
const statusCode = reply.statusCode
|
|
91
95
|
let payload
|
|
92
96
|
try {
|
|
93
|
-
const serializerFn = getSchemaSerializer(reply
|
|
97
|
+
const serializerFn = getSchemaSerializer(reply[kRouteContext], statusCode)
|
|
94
98
|
payload = (serializerFn === false)
|
|
95
99
|
? serializeError({
|
|
96
100
|
error: statusCodes[statusCode + ''],
|
package/lib/handleRequest.js
CHANGED
|
@@ -4,7 +4,8 @@ const { validate: validateSchema } = require('./validation')
|
|
|
4
4
|
const { hookRunner, hookIterator } = require('./hooks')
|
|
5
5
|
const wrapThenable = require('./wrapThenable')
|
|
6
6
|
const {
|
|
7
|
-
kReplyIsError
|
|
7
|
+
kReplyIsError,
|
|
8
|
+
kRouteContext
|
|
8
9
|
} = require('./symbols')
|
|
9
10
|
|
|
10
11
|
function handleRequest (err, request, reply) {
|
|
@@ -17,15 +18,16 @@ function handleRequest (err, request, reply) {
|
|
|
17
18
|
|
|
18
19
|
const method = request.raw.method
|
|
19
20
|
const headers = request.headers
|
|
21
|
+
const context = request[kRouteContext]
|
|
20
22
|
|
|
21
|
-
if (method === 'GET' || method === 'HEAD'
|
|
23
|
+
if (method === 'GET' || method === 'HEAD') {
|
|
22
24
|
handler(request, reply)
|
|
23
25
|
return
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
const contentType = headers['content-type']
|
|
27
29
|
|
|
28
|
-
if (method === 'POST' || method === 'PUT' || method === 'PATCH' || method === 'TRACE') {
|
|
30
|
+
if (method === 'POST' || method === 'PUT' || method === 'PATCH' || method === 'TRACE' || method === 'SEARCH') {
|
|
29
31
|
if (contentType === undefined) {
|
|
30
32
|
if (
|
|
31
33
|
headers['transfer-encoding'] === undefined &&
|
|
@@ -33,10 +35,10 @@ function handleRequest (err, request, reply) {
|
|
|
33
35
|
) { // Request has no body to parse
|
|
34
36
|
handler(request, reply)
|
|
35
37
|
} else {
|
|
36
|
-
|
|
38
|
+
context.contentTypeParser.run('', handler, request, reply)
|
|
37
39
|
}
|
|
38
40
|
} else {
|
|
39
|
-
|
|
41
|
+
context.contentTypeParser.run(contentType, handler, request, reply)
|
|
40
42
|
}
|
|
41
43
|
return
|
|
42
44
|
}
|
|
@@ -49,7 +51,7 @@ function handleRequest (err, request, reply) {
|
|
|
49
51
|
headers['content-length'] !== undefined
|
|
50
52
|
)
|
|
51
53
|
) {
|
|
52
|
-
|
|
54
|
+
context.contentTypeParser.run(contentType, handler, request, reply)
|
|
53
55
|
} else {
|
|
54
56
|
handler(request, reply)
|
|
55
57
|
}
|
|
@@ -62,9 +64,9 @@ function handleRequest (err, request, reply) {
|
|
|
62
64
|
|
|
63
65
|
function handler (request, reply) {
|
|
64
66
|
try {
|
|
65
|
-
if (
|
|
67
|
+
if (request[kRouteContext].preValidation !== null) {
|
|
66
68
|
hookRunner(
|
|
67
|
-
|
|
69
|
+
request[kRouteContext].preValidation,
|
|
68
70
|
hookIterator,
|
|
69
71
|
request,
|
|
70
72
|
reply,
|
|
@@ -87,9 +89,9 @@ function preValidationCallback (err, request, reply) {
|
|
|
87
89
|
return
|
|
88
90
|
}
|
|
89
91
|
|
|
90
|
-
const result = validateSchema(reply
|
|
92
|
+
const result = validateSchema(reply[kRouteContext], request)
|
|
91
93
|
if (result) {
|
|
92
|
-
if (reply.
|
|
94
|
+
if (reply[kRouteContext].attachValidation === false) {
|
|
93
95
|
reply.send(result)
|
|
94
96
|
return
|
|
95
97
|
}
|
|
@@ -98,9 +100,9 @@ function preValidationCallback (err, request, reply) {
|
|
|
98
100
|
}
|
|
99
101
|
|
|
100
102
|
// preHandler hook
|
|
101
|
-
if (
|
|
103
|
+
if (request[kRouteContext].preHandler !== null) {
|
|
102
104
|
hookRunner(
|
|
103
|
-
|
|
105
|
+
request[kRouteContext].preHandler,
|
|
104
106
|
hookIterator,
|
|
105
107
|
request,
|
|
106
108
|
reply,
|
|
@@ -123,7 +125,7 @@ function preHandlerCallback (err, request, reply) {
|
|
|
123
125
|
let result
|
|
124
126
|
|
|
125
127
|
try {
|
|
126
|
-
result =
|
|
128
|
+
result = request[kRouteContext].handler(request, reply)
|
|
127
129
|
} catch (err) {
|
|
128
130
|
reply[kReplyIsError] = true
|
|
129
131
|
reply.send(err)
|