fastify 4.5.3 → 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 +42 -16
- package/docs/Guides/Migration-Guide-V4.md +97 -48
- package/docs/Guides/Plugins-Guide.md +44 -0
- package/docs/Guides/Write-Plugin.md +1 -1
- package/docs/Reference/Logging.md +16 -13
- package/docs/Reference/Reply.md +5 -5
- package/docs/Reference/Request.md +19 -6
- package/docs/Reference/Routes.md +2 -2
- package/docs/Reference/Server.md +24 -2
- package/docs/Reference/Type-Providers.md +5 -19
- package/docs/Reference/TypeScript.md +7 -14
- package/examples/typescript-server.ts +1 -1
- package/fastify.d.ts +2 -2
- package/fastify.js +4 -1
- package/lib/contentTypeParser.js +10 -9
- package/lib/context.js +27 -3
- package/lib/error-handler.js +7 -3
- package/lib/error-serializer.js +13 -40
- package/lib/handleRequest.js +15 -13
- package/lib/reply.js +42 -34
- package/lib/request.js +36 -18
- package/lib/route.js +25 -10
- package/lib/schema-controller.js +7 -1
- package/lib/schemas.js +1 -0
- package/lib/server.js +6 -1
- 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/has-route.test.js +77 -0
- 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/listen.deprecated.test.js +33 -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-special-usage.test.js +29 -0
- package/test/schema-validation.test.js +19 -0
- package/test/search.test.js +169 -30
- package/test/server.test.js +54 -0
- package/test/types/fastify.test-d.ts +9 -0
- package/test/types/route.test-d.ts +11 -0
- package/test/unsupported-httpversion.test.js +0 -26
- package/types/hooks.d.ts +25 -25
- package/types/instance.d.ts +27 -21
- package/types/logger.d.ts +1 -1
- package/types/plugin.d.ts +3 -3
- package/types/reply.d.ts +2 -2
- package/types/request.d.ts +11 -5
- package/types/route.d.ts +9 -9
|
@@ -148,21 +148,14 @@ 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'
|
|
155
155
|
import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox'
|
|
156
156
|
import { Type } from '@sinclair/typebox'
|
|
157
157
|
|
|
158
|
-
const server = Fastify(
|
|
159
|
-
ajv: {
|
|
160
|
-
customOptions: {
|
|
161
|
-
strict: 'log',
|
|
162
|
-
keywords: ['kind', 'modifier'],
|
|
163
|
-
},
|
|
164
|
-
},
|
|
165
|
-
}).withTypeProvider<TypeBoxTypeProvider>()
|
|
158
|
+
const server = Fastify().withTypeProvider<TypeBoxTypeProvider>()
|
|
166
159
|
|
|
167
160
|
server.register(plugin1) // wrong
|
|
168
161
|
server.register(plugin2) // correct
|
|
@@ -213,14 +206,7 @@ import Fastify from 'fastify'
|
|
|
213
206
|
import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox'
|
|
214
207
|
import { registerRoutes } from './routes'
|
|
215
208
|
|
|
216
|
-
const server = Fastify(
|
|
217
|
-
ajv: {
|
|
218
|
-
customOptions: {
|
|
219
|
-
strict: 'log',
|
|
220
|
-
keywords: ['kind', 'modifier'],
|
|
221
|
-
},
|
|
222
|
-
},
|
|
223
|
-
}).withTypeProvider<TypeBoxTypeProvider>()
|
|
209
|
+
const server = Fastify().withTypeProvider<TypeBoxTypeProvider>()
|
|
224
210
|
|
|
225
211
|
registerRoutes(server)
|
|
226
212
|
|
|
@@ -232,7 +218,7 @@ server.listen({ port: 3000 })
|
|
|
232
218
|
import { Type } from '@sinclair/typebox'
|
|
233
219
|
import {
|
|
234
220
|
FastifyInstance,
|
|
235
|
-
|
|
221
|
+
FastifyBaseLogger,
|
|
236
222
|
RawReplyDefaultExpression,
|
|
237
223
|
RawRequestDefaultExpression,
|
|
238
224
|
RawServerDefault
|
|
@@ -243,7 +229,7 @@ type FastifyTypebox = FastifyInstance<
|
|
|
243
229
|
RawServerDefault,
|
|
244
230
|
RawRequestDefaultExpression<RawServerDefault>,
|
|
245
231
|
RawReplyDefaultExpression<RawServerDefault>,
|
|
246
|
-
|
|
232
|
+
FastifyBaseLogger,
|
|
247
233
|
TypeBoxTypeProvider
|
|
248
234
|
>;
|
|
249
235
|
|
|
@@ -61,6 +61,11 @@ in a blank http Fastify server.
|
|
|
61
61
|
*Note: Set `target` property in `tsconfig.json` to `es2017` or greater to avoid
|
|
62
62
|
[FastifyDeprecation](https://github.com/fastify/fastify/issues/3284) warning.*
|
|
63
63
|
|
|
64
|
+
*Note 2: Avoid using ```"moduleResolution": "NodeNext"``` in tsconfig.json with
|
|
65
|
+
```"type": "module"``` in package.json. This combination is currently not
|
|
66
|
+
supported by fastify typing system.
|
|
67
|
+
[ts(2349)](https://github.com/fastify/fastify/issues/4241) warning.*
|
|
68
|
+
|
|
64
69
|
4. Create an `index.ts` file - this will contain the server code
|
|
65
70
|
5. Add the following code block to your file:
|
|
66
71
|
```typescript
|
|
@@ -254,18 +259,6 @@ can do it as follows:
|
|
|
254
259
|
)
|
|
255
260
|
```
|
|
256
261
|
|
|
257
|
-
**Note** For Ajv version 7 and above is required to use the `ajvTypeBoxPlugin`:
|
|
258
|
-
|
|
259
|
-
```typescript
|
|
260
|
-
import Fastify from 'fastify'
|
|
261
|
-
import { ajvTypeBoxPlugin, TypeBoxTypeProvider } from '@fastify/type-provider-typebox'
|
|
262
|
-
|
|
263
|
-
const fastify = Fastify({
|
|
264
|
-
ajv: {
|
|
265
|
-
plugins: [ajvTypeBoxPlugin]
|
|
266
|
-
}
|
|
267
|
-
}).withTypeProvider<TypeBoxTypeProvider>()
|
|
268
|
-
```
|
|
269
262
|
|
|
270
263
|
#### Schemas in JSON Files
|
|
271
264
|
|
|
@@ -1237,8 +1230,8 @@ const plugin: FastifyPlugin<{
|
|
|
1237
1230
|
option2: boolean;
|
|
1238
1231
|
}> = function (instance, opts, done) { }
|
|
1239
1232
|
|
|
1240
|
-
|
|
1241
|
-
|
|
1233
|
+
server().register(plugin, {}) // Error - options object is missing required properties
|
|
1234
|
+
server().register(plugin, { option1: '', option2: true }) // OK - options object contains required properties
|
|
1242
1235
|
```
|
|
1243
1236
|
|
|
1244
1237
|
See the Learn By Example, [Plugins](#plugins) section for more detailed examples
|
package/fastify.d.ts
CHANGED
|
@@ -84,7 +84,7 @@ export type FastifyHttpsOptions<
|
|
|
84
84
|
Server extends https.Server,
|
|
85
85
|
Logger extends FastifyBaseLogger = FastifyLoggerInstance
|
|
86
86
|
> = FastifyServerOptions<Server, Logger> & {
|
|
87
|
-
https: https.ServerOptions
|
|
87
|
+
https: https.ServerOptions | null
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
type FindMyWayVersion<RawServer extends RawServerBase> = RawServer extends http.Server ? HTTPVersion.V1 : HTTPVersion.V2
|
|
@@ -197,7 +197,7 @@ export { FastifyPluginCallback, FastifyPluginAsync, FastifyPluginOptions, Fastif
|
|
|
197
197
|
export { FastifyListenOptions, FastifyInstance, PrintRoutesOptions } from './types/instance'
|
|
198
198
|
export { FastifyLoggerOptions, FastifyBaseLogger, FastifyLoggerInstance, FastifyLogFn, LogLevel } from './types/logger'
|
|
199
199
|
export { FastifyContext, FastifyContextConfig } from './types/context'
|
|
200
|
-
export { RouteHandler, RouteHandlerMethod, RouteOptions, RouteShorthandMethod, RouteShorthandOptions, RouteShorthandOptionsWithHandler } from './types/route'
|
|
200
|
+
export { RouteHandler, RouteHandlerMethod, RouteOptions, RouteShorthandMethod, RouteShorthandOptions, RouteShorthandOptionsWithHandler, RouteGenericInterface } from './types/route'
|
|
201
201
|
export * from './types/register'
|
|
202
202
|
export { FastifyBodyParser, FastifyContentTypeParser, AddContentTypeParser, hasContentTypeParser, getDefaultJsonParser, ProtoAction, ConstructorAction } from './types/content-type-parser'
|
|
203
203
|
export { FastifyError } from '@fastify/error'
|
package/fastify.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const VERSION = '4.
|
|
3
|
+
const VERSION = '4.7.0'
|
|
4
4
|
|
|
5
5
|
const Avvio = require('avvio')
|
|
6
6
|
const http = require('http')
|
|
@@ -267,6 +267,9 @@ function fastify (options) {
|
|
|
267
267
|
// otherwise we should bind it after the declaration
|
|
268
268
|
return router.route.call(this, { options })
|
|
269
269
|
},
|
|
270
|
+
hasRoute: function _route (options) {
|
|
271
|
+
return router.hasRoute.call(this, { options })
|
|
272
|
+
},
|
|
270
273
|
// expose logger instance
|
|
271
274
|
log: logger,
|
|
272
275
|
// type provider
|
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/error-serializer.js
CHANGED
|
@@ -23,14 +23,6 @@ class Serializer {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
asAny (i) {
|
|
27
|
-
return JSON.stringify(i)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
asNull () {
|
|
31
|
-
return 'null'
|
|
32
|
-
}
|
|
33
|
-
|
|
34
26
|
asInteger (i) {
|
|
35
27
|
if (typeof i === 'bigint') {
|
|
36
28
|
return i.toString()
|
|
@@ -47,10 +39,6 @@ class Serializer {
|
|
|
47
39
|
}
|
|
48
40
|
}
|
|
49
41
|
|
|
50
|
-
asIntegerNullable (i) {
|
|
51
|
-
return i === null ? 'null' : this.asInteger(i)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
42
|
asNumber (i) {
|
|
55
43
|
const num = Number(i)
|
|
56
44
|
if (Number.isNaN(num)) {
|
|
@@ -62,54 +50,43 @@ class Serializer {
|
|
|
62
50
|
}
|
|
63
51
|
}
|
|
64
52
|
|
|
65
|
-
asNumberNullable (i) {
|
|
66
|
-
return i === null ? 'null' : this.asNumber(i)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
53
|
asBoolean (bool) {
|
|
70
54
|
return bool && 'true' || 'false' // eslint-disable-line
|
|
71
55
|
}
|
|
72
56
|
|
|
73
|
-
asBooleanNullable (bool) {
|
|
74
|
-
return bool === null ? 'null' : this.asBoolean(bool)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
57
|
asDateTime (date) {
|
|
78
58
|
if (date === null) return '""'
|
|
79
59
|
if (date instanceof Date) {
|
|
80
60
|
return '"' + date.toISOString() + '"'
|
|
81
61
|
}
|
|
62
|
+
if (typeof date === 'string') {
|
|
63
|
+
return '"' + date + '"'
|
|
64
|
+
}
|
|
82
65
|
throw new Error(`The value "${date}" cannot be converted to a date-time.`)
|
|
83
66
|
}
|
|
84
67
|
|
|
85
|
-
asDateTimeNullable (date) {
|
|
86
|
-
return date === null ? 'null' : this.asDateTime(date)
|
|
87
|
-
}
|
|
88
|
-
|
|
89
68
|
asDate (date) {
|
|
90
69
|
if (date === null) return '""'
|
|
91
70
|
if (date instanceof Date) {
|
|
92
71
|
return '"' + new Date(date.getTime() - (date.getTimezoneOffset() * 60000)).toISOString().slice(0, 10) + '"'
|
|
93
72
|
}
|
|
73
|
+
if (typeof date === 'string') {
|
|
74
|
+
return '"' + date + '"'
|
|
75
|
+
}
|
|
94
76
|
throw new Error(`The value "${date}" cannot be converted to a date.`)
|
|
95
77
|
}
|
|
96
78
|
|
|
97
|
-
asDateNullable (date) {
|
|
98
|
-
return date === null ? 'null' : this.asDate(date)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
79
|
asTime (date) {
|
|
102
80
|
if (date === null) return '""'
|
|
103
81
|
if (date instanceof Date) {
|
|
104
82
|
return '"' + new Date(date.getTime() - (date.getTimezoneOffset() * 60000)).toISOString().slice(11, 19) + '"'
|
|
105
83
|
}
|
|
84
|
+
if (typeof date === 'string') {
|
|
85
|
+
return '"' + date + '"'
|
|
86
|
+
}
|
|
106
87
|
throw new Error(`The value "${date}" cannot be converted to a time.`)
|
|
107
88
|
}
|
|
108
89
|
|
|
109
|
-
asTimeNullable (date) {
|
|
110
|
-
return date === null ? 'null' : this.asTime(date)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
90
|
asString (str) {
|
|
114
91
|
const quotes = '"'
|
|
115
92
|
if (str instanceof Date) {
|
|
@@ -129,10 +106,6 @@ class Serializer {
|
|
|
129
106
|
}
|
|
130
107
|
}
|
|
131
108
|
|
|
132
|
-
asStringNullable (str) {
|
|
133
|
-
return str === null ? 'null' : this.asString(str)
|
|
134
|
-
}
|
|
135
|
-
|
|
136
109
|
// magically escape strings for json
|
|
137
110
|
// relying on their charCodeAt
|
|
138
111
|
// everything below 32 needs JSON.stringify()
|
|
@@ -200,7 +173,7 @@ class Serializer {
|
|
|
200
173
|
}
|
|
201
174
|
|
|
202
175
|
json += "\"statusCode\"" + ':'
|
|
203
|
-
json += serializer.asNumber
|
|
176
|
+
json += serializer.asNumber(obj["statusCode"])
|
|
204
177
|
}
|
|
205
178
|
|
|
206
179
|
if (obj["code"] !== undefined) {
|
|
@@ -212,7 +185,7 @@ class Serializer {
|
|
|
212
185
|
}
|
|
213
186
|
|
|
214
187
|
json += "\"code\"" + ':'
|
|
215
|
-
json += serializer.asString
|
|
188
|
+
json += serializer.asString(obj["code"])
|
|
216
189
|
}
|
|
217
190
|
|
|
218
191
|
if (obj["error"] !== undefined) {
|
|
@@ -224,7 +197,7 @@ class Serializer {
|
|
|
224
197
|
}
|
|
225
198
|
|
|
226
199
|
json += "\"error\"" + ':'
|
|
227
|
-
json += serializer.asString
|
|
200
|
+
json += serializer.asString(obj["error"])
|
|
228
201
|
}
|
|
229
202
|
|
|
230
203
|
if (obj["message"] !== undefined) {
|
|
@@ -236,7 +209,7 @@ class Serializer {
|
|
|
236
209
|
}
|
|
237
210
|
|
|
238
211
|
json += "\"message\"" + ':'
|
|
239
|
-
json += serializer.asString
|
|
212
|
+
json += serializer.asString(obj["message"])
|
|
240
213
|
}
|
|
241
214
|
|
|
242
215
|
json += '}'
|
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)
|