fastify 4.3.0 → 4.4.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 -0
- package/docs/Reference/Hooks.md +4 -1
- package/docs/Reference/Logging.md +1 -1
- package/docs/Reference/Reply.md +1 -0
- package/docs/Reference/Routes.md +4 -2
- package/docs/Reference/Server.md +4 -1
- package/fastify.js +2 -2
- package/lib/handleRequest.js +2 -2
- package/lib/httpMethods.js +22 -0
- package/lib/route.js +1 -1
- package/package.json +2 -2
- package/test/copy.test.js +41 -0
- package/test/internals/all.test.js +8 -2
- package/test/internals/reply.test.js +4 -1
- package/test/lock.test.js +73 -0
- package/test/mkcol.test.js +38 -0
- package/test/move.test.js +45 -0
- package/test/propfind.test.js +108 -0
- package/test/proppatch.test.js +78 -0
- package/test/search.test.js +100 -0
- package/test/trace.test.js +21 -0
- package/test/types/logger.test-d.ts +4 -5
- package/test/types/reply.test-d.ts +44 -3
- package/test/types/request.test-d.ts +9 -28
- package/test/types/type-provider.test-d.ts +3 -1
- package/test/unlock.test.js +41 -0
- package/types/logger.d.ts +7 -4
- package/types/reply.d.ts +7 -6
- package/types/request.d.ts +2 -2
- package/types/type-provider.d.ts +1 -14
- package/types/utils.d.ts +2 -1
package/docs/Guides/Ecosystem.md
CHANGED
|
@@ -112,6 +112,14 @@ section.
|
|
|
112
112
|
- [`@fastify/swagger`](https://github.com/fastify/fastify-swagger) Plugin for
|
|
113
113
|
serving Swagger/OpenAPI documentation for Fastify, supporting dynamic
|
|
114
114
|
generation.
|
|
115
|
+
- [`@fastify/type-provider-json-schema-to-ts`](https://github.com/fastify/fastify-type-provider-json-schema-to-ts)
|
|
116
|
+
Fastify
|
|
117
|
+
[type provider](https://www.fastify.io/docs/latest/Reference/Type-Providers/)
|
|
118
|
+
for [json-schema-to-ts](https://github.com/ThomasAribart/json-schema-to-ts).
|
|
119
|
+
- [`@fastify/type-provider-typebox`](https://github.com/fastify/fastify-type-provider-typebox)
|
|
120
|
+
Fastify
|
|
121
|
+
[type provider](https://www.fastify.io/docs/latest/Reference/Type-Providers/)
|
|
122
|
+
for [Typebox](https://github.com/sinclairzx81/typebox).
|
|
115
123
|
- [`@fastify/under-pressure`](https://github.com/fastify/under-pressure) Measure
|
|
116
124
|
process load with automatic handling of _"Service Unavailable"_ plugin for
|
|
117
125
|
Fastify.
|
|
@@ -147,6 +155,9 @@ section.
|
|
|
147
155
|
- [`@immobiliarelabs/fastify-sentry`](https://github.com/immobiliare/fastify-sentry)
|
|
148
156
|
Sentry errors handler that just works! Install, add your DSN and you're good
|
|
149
157
|
to go!
|
|
158
|
+
- [`@mateonunez/fastify-lyra`](https://github.com/mateonunez/fastify-lyra)
|
|
159
|
+
A plugin to implement [Lyra](https://github.com/nearform/lyra) search engine
|
|
160
|
+
on Fastify
|
|
150
161
|
- [`@mgcrea/fastify-graceful-exit`](https://github.com/mgcrea/fastify-graceful-exit)
|
|
151
162
|
A plugin to close the server gracefully
|
|
152
163
|
- [`@mgcrea/fastify-request-logger`](https://github.com/mgcrea/fastify-request-logger)
|
|
@@ -215,6 +226,8 @@ section.
|
|
|
215
226
|
to add [boom](https://github.com/hapijs/boom) support.
|
|
216
227
|
- [`fastify-bree`](https://github.com/climba03003/fastify-bree) Fastify plugin
|
|
217
228
|
to add [bree](https://github.com/breejs/bree) support.
|
|
229
|
+
- [`fastify-bugsnag`](https://github.com/ZigaStrgar/fastify-bugsnag) Fastify plugin
|
|
230
|
+
to add support for [Bugsnag](https://www.bugsnag.com/) error reporting.
|
|
218
231
|
- [`fastify-casbin`](https://github.com/nearform/fastify-casbin) Casbin support
|
|
219
232
|
for Fastify.
|
|
220
233
|
- [`fastify-casbin-rest`](https://github.com/nearform/fastify-casbin-rest)
|
|
@@ -328,6 +341,8 @@ section.
|
|
|
328
341
|
authentication for Fastify-based web apps.
|
|
329
342
|
- [`fastify-kafkajs`](https://github.com/kffl/fastify-kafkajs) Fastify plugin
|
|
330
343
|
that adds support for KafkaJS - a modern Apache Kafka client library.
|
|
344
|
+
- [`fastify-keycloak-adapter`](https://github.com/yubinTW/fastify-keycloak-adapter)
|
|
345
|
+
A keycloak adapter for a Fastify app.
|
|
331
346
|
- [`fastify-knexjs`](https://github.com/chapuletta/fastify-knexjs) Fastify
|
|
332
347
|
plugin for support KnexJS Query Builder.
|
|
333
348
|
- [`fastify-knexjs-mock`](https://github.com/chapuletta/fastify-knexjs-mock)
|
|
@@ -508,6 +523,10 @@ section.
|
|
|
508
523
|
TOTP (e.g. for 2FA).
|
|
509
524
|
- [`fastify-twitch-ebs-tools`](https://github.com/lukemnet/fastify-twitch-ebs-tools)
|
|
510
525
|
Useful functions for Twitch Extension Backend Services (EBS).
|
|
526
|
+
- [`fastify-type-provider-zod`](https://github.com/turkerdev/fastify-type-provider-zod)
|
|
527
|
+
Fastify
|
|
528
|
+
[type provider](https://www.fastify.io/docs/latest/Reference/Type-Providers/)
|
|
529
|
+
for [zod](https://github.com/colinhacks/zod).
|
|
511
530
|
- [`fastify-typeorm-plugin`](https://github.com/inthepocket/fastify-typeorm-plugin)
|
|
512
531
|
Fastify plugin to work with TypeORM.
|
|
513
532
|
- [`fastify-vhost`](https://github.com/patrickpissurno/fastify-vhost) Proxy
|
package/docs/Reference/Hooks.md
CHANGED
|
@@ -244,6 +244,9 @@ The `onResponse` hook is executed when a response has been sent, so you will not
|
|
|
244
244
|
be able to send more data to the client. It can however be useful for sending
|
|
245
245
|
data to external services, for example, to gather statistics.
|
|
246
246
|
|
|
247
|
+
**Note:** setting `disableRequestLogging` to `true` will disable any error log
|
|
248
|
+
inside the `onResponse` hook. In this case use `try - catch` to log errors.
|
|
249
|
+
|
|
247
250
|
### onTimeout
|
|
248
251
|
|
|
249
252
|
```js
|
|
@@ -287,7 +290,7 @@ fastify.addHook('preHandler', (request, reply, done) => {
|
|
|
287
290
|
|
|
288
291
|
Or if you're using `async/await` you can just throw an error:
|
|
289
292
|
```js
|
|
290
|
-
fastify.addHook('
|
|
293
|
+
fastify.addHook('onRequest', async (request, reply) => {
|
|
291
294
|
throw new Error('Some error')
|
|
292
295
|
})
|
|
293
296
|
```
|
|
@@ -170,7 +170,7 @@ app.addHook('preHandler', function (req, reply, done) {
|
|
|
170
170
|
You can also supply your own logger instance. Instead of passing configuration
|
|
171
171
|
options, pass the instance. The logger you supply must conform to the Pino
|
|
172
172
|
interface; that is, it must have the following methods: `info`, `error`,
|
|
173
|
-
`debug`, `fatal`, `warn`, `trace`, `child`.
|
|
173
|
+
`debug`, `fatal`, `warn`, `trace`, `silent`, `child` and a string property `level`.
|
|
174
174
|
|
|
175
175
|
Example:
|
|
176
176
|
|
package/docs/Reference/Reply.md
CHANGED
|
@@ -767,6 +767,7 @@ Fastify natively handles promises and supports async-await.
|
|
|
767
767
|
|
|
768
768
|
*Note that in the following examples we are not using reply.send.*
|
|
769
769
|
```js
|
|
770
|
+
const { promisify } = require('util')
|
|
770
771
|
const delay = promisify(setTimeout)
|
|
771
772
|
|
|
772
773
|
fastify.get('/promises', options, function (request, reply) {
|
package/docs/Reference/Routes.md
CHANGED
|
@@ -32,8 +32,10 @@ fastify.route(options)
|
|
|
32
32
|
### Routes options
|
|
33
33
|
<a id="options"></a>
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
`'POST'`, `'PUT'
|
|
35
|
+
* `method`: currently it supports `'DELETE'`, `'GET'`, `'HEAD'`, `'PATCH'`,
|
|
36
|
+
`'POST'`, `'PUT'`, `'OPTIONS'`, `'SEARCH'`, `'TRACE'`, `'PROPFIND'`,
|
|
37
|
+
`'PROPPATCH'`, `'MKCOL'`, `'COPY'`, `'MOVE'`, `'LOCK'` and `'UNLOCK'`.
|
|
38
|
+
It could also be an array of methods.
|
|
37
39
|
* `url`: the path of the URL to match this route (alias: `path`).
|
|
38
40
|
* `schema`: an object containing the schemas for the request and response. They
|
|
39
41
|
need to be in [JSON Schema](https://json-schema.org/) format, check
|
package/docs/Reference/Server.md
CHANGED
|
@@ -890,7 +890,7 @@ fastify.ready().then(() => {
|
|
|
890
890
|
Starts the server and internally waits for the `.ready()` event. The signature
|
|
891
891
|
is `.listen([options][, callback])`. Both the `options` object and the
|
|
892
892
|
`callback` parameters follow the [Node.js
|
|
893
|
-
core]
|
|
893
|
+
core](https://nodejs.org/api/net.html#serverlistenoptions-callback) parameter
|
|
894
894
|
definitions.
|
|
895
895
|
|
|
896
896
|
By default, the server will listen on the address(es) resolved by `localhost`
|
|
@@ -1402,6 +1402,9 @@ handlers. *async-await* is supported as well.
|
|
|
1402
1402
|
*Note: If the error `statusCode` is less than 400, Fastify will automatically
|
|
1403
1403
|
set it at 500 before calling the error handler.*
|
|
1404
1404
|
|
|
1405
|
+
*Also note* that `setErrorHandler` will ***not*** catch any error inside
|
|
1406
|
+
an `onResponse` hook because the response has already been sent to the client.
|
|
1407
|
+
|
|
1405
1408
|
```js
|
|
1406
1409
|
fastify.setErrorHandler(function (error, request, reply) {
|
|
1407
1410
|
// Log error
|
package/fastify.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const VERSION = '4.
|
|
3
|
+
const VERSION = '4.4.0'
|
|
4
4
|
|
|
5
5
|
const Avvio = require('avvio')
|
|
6
6
|
const http = require('http')
|
|
@@ -34,7 +34,7 @@ const {
|
|
|
34
34
|
const { createServer, compileValidateHTTPVersion } = require('./lib/server')
|
|
35
35
|
const Reply = require('./lib/reply')
|
|
36
36
|
const Request = require('./lib/request')
|
|
37
|
-
const supportedMethods =
|
|
37
|
+
const { supportedMethods } = require('./lib/httpMethods')
|
|
38
38
|
const decorator = require('./lib/decorate')
|
|
39
39
|
const ContentTypeParser = require('./lib/contentTypeParser')
|
|
40
40
|
const SchemaController = require('./lib/schema-controller')
|
package/lib/handleRequest.js
CHANGED
|
@@ -18,14 +18,14 @@ function handleRequest (err, request, reply) {
|
|
|
18
18
|
const method = request.raw.method
|
|
19
19
|
const headers = request.headers
|
|
20
20
|
|
|
21
|
-
if (method === 'GET' || method === 'HEAD') {
|
|
21
|
+
if (method === 'GET' || method === 'HEAD' || method === 'SEARCH') {
|
|
22
22
|
handler(request, reply)
|
|
23
23
|
return
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
const contentType = headers['content-type']
|
|
27
27
|
|
|
28
|
-
if (method === 'POST' || method === 'PUT' || method === 'PATCH') {
|
|
28
|
+
if (method === 'POST' || method === 'PUT' || method === 'PATCH' || method === 'TRACE') {
|
|
29
29
|
if (contentType === undefined) {
|
|
30
30
|
if (
|
|
31
31
|
headers['transfer-encoding'] === undefined &&
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
supportedMethods: [
|
|
5
|
+
'DELETE',
|
|
6
|
+
'GET',
|
|
7
|
+
'HEAD',
|
|
8
|
+
'PATCH',
|
|
9
|
+
'POST',
|
|
10
|
+
'PUT',
|
|
11
|
+
'OPTIONS',
|
|
12
|
+
'PROPFIND',
|
|
13
|
+
'PROPPATCH',
|
|
14
|
+
'MKCOL',
|
|
15
|
+
'COPY',
|
|
16
|
+
'MOVE',
|
|
17
|
+
'LOCK',
|
|
18
|
+
'UNLOCK',
|
|
19
|
+
'TRACE',
|
|
20
|
+
'SEARCH'
|
|
21
|
+
]
|
|
22
|
+
}
|
package/lib/route.js
CHANGED
|
@@ -4,7 +4,7 @@ const FindMyWay = require('find-my-way')
|
|
|
4
4
|
const Context = require('./context')
|
|
5
5
|
const handleRequest = require('./handleRequest')
|
|
6
6
|
const { hookRunner, hookIterator, lifecycleHooks } = require('./hooks')
|
|
7
|
-
const supportedMethods =
|
|
7
|
+
const { supportedMethods } = require('./httpMethods')
|
|
8
8
|
const { normalizeSchema } = require('./schemas')
|
|
9
9
|
const { parseHeadOnSendHandlers } = require('./headRoute')
|
|
10
10
|
const warning = require('./warnings')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fastify",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.4.0",
|
|
4
4
|
"description": "Fast and low overhead web framework, for Node.js",
|
|
5
5
|
"main": "fastify.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -159,7 +159,7 @@
|
|
|
159
159
|
"json-schema-to-ts": "^2.5.3",
|
|
160
160
|
"JSONStream": "^1.3.5",
|
|
161
161
|
"license-checker": "^25.0.1",
|
|
162
|
-
"markdownlint-cli2": "^0.
|
|
162
|
+
"markdownlint-cli2": "^0.5.0",
|
|
163
163
|
"proxyquire": "^2.1.3",
|
|
164
164
|
"pump": "^3.0.0",
|
|
165
165
|
"self-cert": "^2.0.0",
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const t = require('tap')
|
|
4
|
+
const test = t.test
|
|
5
|
+
const sget = require('simple-get').concat
|
|
6
|
+
const fastify = require('..')()
|
|
7
|
+
|
|
8
|
+
test('can be created - copy', t => {
|
|
9
|
+
t.plan(1)
|
|
10
|
+
try {
|
|
11
|
+
fastify.route({
|
|
12
|
+
method: 'COPY',
|
|
13
|
+
url: '*',
|
|
14
|
+
handler: function (req, reply) {
|
|
15
|
+
reply.code(204).send()
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
t.pass()
|
|
19
|
+
} catch (e) {
|
|
20
|
+
t.fail()
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
fastify.listen({ port: 0 }, err => {
|
|
25
|
+
t.error(err)
|
|
26
|
+
t.teardown(() => { fastify.close() })
|
|
27
|
+
|
|
28
|
+
test('request - copy', t => {
|
|
29
|
+
t.plan(2)
|
|
30
|
+
sget({
|
|
31
|
+
url: `http://localhost:${fastify.server.address().port}/test.txt`,
|
|
32
|
+
method: 'COPY',
|
|
33
|
+
headers: {
|
|
34
|
+
Destination: '/test2.txt'
|
|
35
|
+
}
|
|
36
|
+
}, (err, response, body) => {
|
|
37
|
+
t.error(err)
|
|
38
|
+
t.equal(response.statusCode, 204)
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
})
|
|
@@ -3,9 +3,15 @@
|
|
|
3
3
|
const t = require('tap')
|
|
4
4
|
const test = t.test
|
|
5
5
|
const Fastify = require('../..')
|
|
6
|
-
const supportedMethods =
|
|
6
|
+
const { supportedMethods } = require('../../lib/httpMethods')
|
|
7
7
|
|
|
8
8
|
test('fastify.all should add all the methods to the same url', t => {
|
|
9
|
+
const requirePayload = [
|
|
10
|
+
'POST',
|
|
11
|
+
'PUT',
|
|
12
|
+
'PATCH'
|
|
13
|
+
]
|
|
14
|
+
|
|
9
15
|
t.plan(supportedMethods.length * 2)
|
|
10
16
|
|
|
11
17
|
const fastify = Fastify()
|
|
@@ -22,7 +28,7 @@ test('fastify.all should add all the methods to the same url', t => {
|
|
|
22
28
|
method
|
|
23
29
|
}
|
|
24
30
|
|
|
25
|
-
if (method
|
|
31
|
+
if (requirePayload.includes(method)) {
|
|
26
32
|
options.payload = { hello: 'world' }
|
|
27
33
|
}
|
|
28
34
|
|
|
@@ -1044,7 +1044,7 @@ test('reply.hasHeader returns correct values', t => {
|
|
|
1044
1044
|
})
|
|
1045
1045
|
|
|
1046
1046
|
test('reply.getHeader returns correct values', t => {
|
|
1047
|
-
t.plan(
|
|
1047
|
+
t.plan(5)
|
|
1048
1048
|
|
|
1049
1049
|
const fastify = require('../../')()
|
|
1050
1050
|
|
|
@@ -1055,6 +1055,9 @@ test('reply.getHeader returns correct values', t => {
|
|
|
1055
1055
|
reply.header('x-foo', 'bar')
|
|
1056
1056
|
t.strictSame(reply.getHeader('x-foo'), 'bar')
|
|
1057
1057
|
|
|
1058
|
+
reply.header('x-foo', 42)
|
|
1059
|
+
t.strictSame(reply.getHeader('x-foo'), 42)
|
|
1060
|
+
|
|
1058
1061
|
reply.header('set-cookie', 'one')
|
|
1059
1062
|
reply.header('set-cookie', 'two')
|
|
1060
1063
|
t.strictSame(reply.getHeader('set-cookie'), ['one', 'two'])
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const t = require('tap')
|
|
4
|
+
const test = t.test
|
|
5
|
+
const sget = require('simple-get').concat
|
|
6
|
+
const fastify = require('..')()
|
|
7
|
+
|
|
8
|
+
test('can be created - lock', t => {
|
|
9
|
+
t.plan(1)
|
|
10
|
+
try {
|
|
11
|
+
fastify.route({
|
|
12
|
+
method: 'LOCK',
|
|
13
|
+
url: '*',
|
|
14
|
+
handler: function (req, reply) {
|
|
15
|
+
reply
|
|
16
|
+
.code(200)
|
|
17
|
+
.send(`<?xml version="1.0" encoding="utf-8" ?>
|
|
18
|
+
<D:prop xmlns:D="DAV:">
|
|
19
|
+
<D:lockdiscovery>
|
|
20
|
+
<D:activelock>
|
|
21
|
+
<D:locktype>
|
|
22
|
+
<D:write/>
|
|
23
|
+
</D:locktype>
|
|
24
|
+
<D:lockscope>
|
|
25
|
+
<D:exclusive/>
|
|
26
|
+
</D:lockscope>
|
|
27
|
+
<D:depth>infinity</D:depth>
|
|
28
|
+
<D:owner>
|
|
29
|
+
<D:href>http://example.org/~ejw/contact.html</D:href>
|
|
30
|
+
</D:owner>
|
|
31
|
+
<D:timeout>Second-604800</D:timeout>
|
|
32
|
+
<D:locktoken>
|
|
33
|
+
<D:href>urn:uuid:e71d4fae-5dec-22d6-fea5-00a0c91e6be4</:href>
|
|
34
|
+
</D:locktoken>
|
|
35
|
+
<D:lockroot>
|
|
36
|
+
<D:href>http://example.com/workspace/webdav/proposal.oc</D:href>
|
|
37
|
+
</D:lockroot>
|
|
38
|
+
</D:activelock>
|
|
39
|
+
</D:lockdiscovery>
|
|
40
|
+
</D:prop>`
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
t.pass()
|
|
45
|
+
} catch (e) {
|
|
46
|
+
t.fail()
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
fastify.listen({ port: 0 }, err => {
|
|
51
|
+
t.error(err)
|
|
52
|
+
t.teardown(() => { fastify.close() })
|
|
53
|
+
|
|
54
|
+
test('request - lock', t => {
|
|
55
|
+
t.plan(3)
|
|
56
|
+
sget({
|
|
57
|
+
url: `http://localhost:${fastify.server.address().port}/test/a.txt`,
|
|
58
|
+
body: `<?xml version="1.0" encoding="utf-8" ?>
|
|
59
|
+
<D:lockinfo xmlns:D='DAV:'>
|
|
60
|
+
<D:lockscope> <D:exclusive/> </D:lockscope>
|
|
61
|
+
<D:locktype> <D:write/> </D:locktype>
|
|
62
|
+
<D:owner>
|
|
63
|
+
<D:href>http://example.org/~ejw/contact.html</D:href>
|
|
64
|
+
</D:owner>
|
|
65
|
+
</D:lockinfo> `,
|
|
66
|
+
method: 'LOCK'
|
|
67
|
+
}, (err, response, body) => {
|
|
68
|
+
t.error(err)
|
|
69
|
+
t.equal(response.statusCode, 200)
|
|
70
|
+
t.equal(response.headers['content-length'], '' + body.length)
|
|
71
|
+
})
|
|
72
|
+
})
|
|
73
|
+
})
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const t = require('tap')
|
|
4
|
+
const test = t.test
|
|
5
|
+
const sget = require('simple-get').concat
|
|
6
|
+
const fastify = require('..')()
|
|
7
|
+
|
|
8
|
+
test('can be created - mkcol', t => {
|
|
9
|
+
t.plan(1)
|
|
10
|
+
try {
|
|
11
|
+
fastify.route({
|
|
12
|
+
method: 'MKCOL',
|
|
13
|
+
url: '*',
|
|
14
|
+
handler: function (req, reply) {
|
|
15
|
+
reply.code(201).send()
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
t.pass()
|
|
19
|
+
} catch (e) {
|
|
20
|
+
t.fail()
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
fastify.listen({ port: 0 }, err => {
|
|
25
|
+
t.error(err)
|
|
26
|
+
t.teardown(() => { fastify.close() })
|
|
27
|
+
|
|
28
|
+
test('request - mkcol', t => {
|
|
29
|
+
t.plan(2)
|
|
30
|
+
sget({
|
|
31
|
+
url: `http://localhost:${fastify.server.address().port}/test/`,
|
|
32
|
+
method: 'MKCOL'
|
|
33
|
+
}, (err, response, body) => {
|
|
34
|
+
t.error(err)
|
|
35
|
+
t.equal(response.statusCode, 201)
|
|
36
|
+
})
|
|
37
|
+
})
|
|
38
|
+
})
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const t = require('tap')
|
|
4
|
+
const test = t.test
|
|
5
|
+
const sget = require('simple-get').concat
|
|
6
|
+
const fastify = require('..')()
|
|
7
|
+
|
|
8
|
+
test('shorthand - move', t => {
|
|
9
|
+
t.plan(1)
|
|
10
|
+
try {
|
|
11
|
+
fastify.route({
|
|
12
|
+
method: 'MOVE',
|
|
13
|
+
url: '*',
|
|
14
|
+
handler: function (req, reply) {
|
|
15
|
+
const destination = req.headers.destination
|
|
16
|
+
reply.code(201)
|
|
17
|
+
.header('location', destination)
|
|
18
|
+
.send()
|
|
19
|
+
}
|
|
20
|
+
})
|
|
21
|
+
t.pass()
|
|
22
|
+
} catch (e) {
|
|
23
|
+
t.fail()
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
fastify.listen({ port: 0 }, err => {
|
|
28
|
+
t.error(err)
|
|
29
|
+
t.teardown(() => { fastify.close() })
|
|
30
|
+
|
|
31
|
+
test('request - move', t => {
|
|
32
|
+
t.plan(3)
|
|
33
|
+
sget({
|
|
34
|
+
url: `http://localhost:${fastify.server.address().port}/test.txt`,
|
|
35
|
+
method: 'MOVE',
|
|
36
|
+
headers: {
|
|
37
|
+
Destination: '/test2.txt'
|
|
38
|
+
}
|
|
39
|
+
}, (err, response, body) => {
|
|
40
|
+
t.error(err)
|
|
41
|
+
t.equal(response.statusCode, 201)
|
|
42
|
+
t.equal(response.headers.location, '/test2.txt')
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
})
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const t = require('tap')
|
|
4
|
+
const test = t.test
|
|
5
|
+
const sget = require('simple-get').concat
|
|
6
|
+
const fastify = require('..')()
|
|
7
|
+
|
|
8
|
+
test('can be created - propfind', t => {
|
|
9
|
+
t.plan(1)
|
|
10
|
+
try {
|
|
11
|
+
fastify.route({
|
|
12
|
+
method: 'PROPFIND',
|
|
13
|
+
url: '*',
|
|
14
|
+
handler: function (req, reply) {
|
|
15
|
+
return reply.code(207)
|
|
16
|
+
.send(`<?xml version="1.0" encoding="utf-8"?>
|
|
17
|
+
<D:multistatus xmlns:D="DAV:">
|
|
18
|
+
<D:response xmlns:lp1="DAV:">
|
|
19
|
+
<D:href>/</D:href>
|
|
20
|
+
<D:propstat>
|
|
21
|
+
<D:prop>
|
|
22
|
+
<lp1:resourcetype>
|
|
23
|
+
<D:collection/>
|
|
24
|
+
</lp1:resourcetype>
|
|
25
|
+
<lp1:creationdate>2022-04-13T12:35:30Z</lp1:creationdate>
|
|
26
|
+
<lp1:getlastmodified>Wed, 13 Apr 2022 12:35:30 GMT</lp1:getlastmodified>
|
|
27
|
+
<lp1:getetag>"e0-5dc8869b53ef1"</lp1:getetag>
|
|
28
|
+
<D:supportedlock>
|
|
29
|
+
<D:lockentry>
|
|
30
|
+
<D:lockscope>
|
|
31
|
+
<D:exclusive/>
|
|
32
|
+
</D:lockscope>
|
|
33
|
+
<D:locktype>
|
|
34
|
+
<D:write/>
|
|
35
|
+
</D:locktype>
|
|
36
|
+
</D:lockentry>
|
|
37
|
+
<D:lockentry>
|
|
38
|
+
<D:lockscope>
|
|
39
|
+
<D:shared/>
|
|
40
|
+
</D:lockscope>
|
|
41
|
+
<D:locktype>
|
|
42
|
+
<D:write/>
|
|
43
|
+
</D:locktype>
|
|
44
|
+
</D:lockentry>
|
|
45
|
+
</D:supportedlock>
|
|
46
|
+
<D:lockdiscovery/>
|
|
47
|
+
<D:getcontenttype>httpd/unix-directory</D:getcontenttype>
|
|
48
|
+
</D:prop>
|
|
49
|
+
<D:status>HTTP/1.1 200 OK</D:status>
|
|
50
|
+
</D:propstat>
|
|
51
|
+
</D:response>
|
|
52
|
+
</D:multistatus>`
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
t.pass()
|
|
57
|
+
} catch (e) {
|
|
58
|
+
t.fail()
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
fastify.listen({ port: 0 }, err => {
|
|
63
|
+
t.error(err)
|
|
64
|
+
t.teardown(() => { fastify.close() })
|
|
65
|
+
|
|
66
|
+
test('request - propfind', t => {
|
|
67
|
+
t.plan(3)
|
|
68
|
+
sget({
|
|
69
|
+
url: `http://localhost:${fastify.server.address().port}/`,
|
|
70
|
+
method: 'PROPFIND'
|
|
71
|
+
}, (err, response, body) => {
|
|
72
|
+
t.error(err)
|
|
73
|
+
t.equal(response.statusCode, 207)
|
|
74
|
+
t.equal(response.headers['content-length'], '' + body.length)
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
test('request with other path - propfind', t => {
|
|
79
|
+
t.plan(3)
|
|
80
|
+
sget({
|
|
81
|
+
url: `http://localhost:${fastify.server.address().port}/test`,
|
|
82
|
+
method: 'PROPFIND'
|
|
83
|
+
}, (err, response, body) => {
|
|
84
|
+
t.error(err)
|
|
85
|
+
t.equal(response.statusCode, 207)
|
|
86
|
+
t.equal(response.headers['content-length'], '' + body.length)
|
|
87
|
+
})
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
test('request with body - propfind', t => {
|
|
91
|
+
t.plan(3)
|
|
92
|
+
sget({
|
|
93
|
+
url: `http://localhost:${fastify.server.address().port}/test`,
|
|
94
|
+
body: `<?xml version="1.0" encoding="utf-8" ?>
|
|
95
|
+
<D:propfind xmlns:D="DAV:">
|
|
96
|
+
<D:prop xmlns:R="http://ns.example.com/boxschema/">
|
|
97
|
+
<R:bigbox/> <R:author/> <R:DingALing/> <R:Random/>
|
|
98
|
+
</D:prop>
|
|
99
|
+
</D:propfind>
|
|
100
|
+
`,
|
|
101
|
+
method: 'PROPFIND'
|
|
102
|
+
}, (err, response, body) => {
|
|
103
|
+
t.error(err)
|
|
104
|
+
t.equal(response.statusCode, 207)
|
|
105
|
+
t.equal(response.headers['content-length'], '' + body.length)
|
|
106
|
+
})
|
|
107
|
+
})
|
|
108
|
+
})
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const t = require('tap')
|
|
4
|
+
const test = t.test
|
|
5
|
+
const sget = require('simple-get').concat
|
|
6
|
+
const fastify = require('..')()
|
|
7
|
+
|
|
8
|
+
test('shorthand - proppatch', t => {
|
|
9
|
+
t.plan(1)
|
|
10
|
+
try {
|
|
11
|
+
fastify.route({
|
|
12
|
+
method: 'PROPPATCH',
|
|
13
|
+
url: '*',
|
|
14
|
+
handler: function (req, reply) {
|
|
15
|
+
reply
|
|
16
|
+
.code(207)
|
|
17
|
+
.send(`<?xml version="1.0" encoding="utf-8" ?>
|
|
18
|
+
<D:multistatus xmlns:D="DAV:"
|
|
19
|
+
xmlns:Z="http://ns.example.com/standards/z39.50/">
|
|
20
|
+
<D:response>
|
|
21
|
+
<D:href>http://www.example.com/bar.html</D:href>
|
|
22
|
+
<D:propstat>
|
|
23
|
+
<D:prop>
|
|
24
|
+
<Z:Authors/>
|
|
25
|
+
</D:prop>
|
|
26
|
+
<D:status>HTTP/1.1 424 Failed Dependency</D:status>
|
|
27
|
+
</D:propstat>
|
|
28
|
+
<D:propstat>
|
|
29
|
+
<D:prop>
|
|
30
|
+
<Z:Copyright-Owner/>
|
|
31
|
+
</D:prop>
|
|
32
|
+
<D:status>HTTP/1.1 409 Conflict</D:status>
|
|
33
|
+
</D:propstat>
|
|
34
|
+
<D:responsedescription> Copyright Owner cannot be deleted or altered.</D:responsedescription>
|
|
35
|
+
</D:response>
|
|
36
|
+
</D:multistatus>`
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
t.pass()
|
|
41
|
+
} catch (e) {
|
|
42
|
+
t.fail()
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
fastify.listen({ port: 0 }, err => {
|
|
47
|
+
t.error(err)
|
|
48
|
+
t.teardown(() => { fastify.close() })
|
|
49
|
+
|
|
50
|
+
test('request - proppatch', t => {
|
|
51
|
+
t.plan(3)
|
|
52
|
+
sget({
|
|
53
|
+
url: `http://localhost:${fastify.server.address().port}/test/a.txt`,
|
|
54
|
+
body: `<?xml version="1.0" encoding="utf-8" ?>
|
|
55
|
+
<D:propertyupdate xmlns:D="DAV:"
|
|
56
|
+
xmlns:Z="http://ns.example.com/standards/z39.50/">
|
|
57
|
+
<D:set>
|
|
58
|
+
<D:prop>
|
|
59
|
+
<Z:Authors>
|
|
60
|
+
<Z:Author>Jim Whitehead</Z:Author>
|
|
61
|
+
<Z:Author>Roy Fielding</Z:Author>
|
|
62
|
+
</Z:Authors>
|
|
63
|
+
</D:prop>
|
|
64
|
+
</D:set>
|
|
65
|
+
<D:remove>
|
|
66
|
+
<D:prop>
|
|
67
|
+
<Z:Copyright-Owner/>
|
|
68
|
+
</D:prop>
|
|
69
|
+
</D:remove>
|
|
70
|
+
</D:propertyupdate>`,
|
|
71
|
+
method: 'PROPPATCH'
|
|
72
|
+
}, (err, response, body) => {
|
|
73
|
+
t.error(err)
|
|
74
|
+
t.equal(response.statusCode, 207)
|
|
75
|
+
t.equal(response.headers['content-length'], '' + body.length)
|
|
76
|
+
})
|
|
77
|
+
})
|
|
78
|
+
})
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const t = require('tap')
|
|
4
|
+
const test = t.test
|
|
5
|
+
const fastify = require('..')()
|
|
6
|
+
|
|
7
|
+
const schema = {
|
|
8
|
+
schema: {
|
|
9
|
+
response: {
|
|
10
|
+
'2xx': {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
hello: {
|
|
14
|
+
type: 'string'
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const querySchema = {
|
|
23
|
+
schema: {
|
|
24
|
+
querystring: {
|
|
25
|
+
type: 'object',
|
|
26
|
+
properties: {
|
|
27
|
+
hello: {
|
|
28
|
+
type: 'integer'
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const paramsSchema = {
|
|
36
|
+
schema: {
|
|
37
|
+
params: {
|
|
38
|
+
type: 'object',
|
|
39
|
+
properties: {
|
|
40
|
+
foo: {
|
|
41
|
+
type: 'string'
|
|
42
|
+
},
|
|
43
|
+
test: {
|
|
44
|
+
type: 'integer'
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
test('shorthand - search', t => {
|
|
52
|
+
t.plan(1)
|
|
53
|
+
try {
|
|
54
|
+
fastify.route({
|
|
55
|
+
method: 'SEARCH',
|
|
56
|
+
url: '/',
|
|
57
|
+
schema,
|
|
58
|
+
handler: function (request, reply) {
|
|
59
|
+
reply.code(200).send({ hello: 'world' })
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
t.pass()
|
|
63
|
+
} catch (e) {
|
|
64
|
+
t.fail()
|
|
65
|
+
}
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test('shorthand - search params', t => {
|
|
69
|
+
t.plan(1)
|
|
70
|
+
try {
|
|
71
|
+
fastify.route({
|
|
72
|
+
method: 'SEARCH',
|
|
73
|
+
url: '/params/:foo/:test',
|
|
74
|
+
paramsSchema,
|
|
75
|
+
handler: function (request, reply) {
|
|
76
|
+
reply.code(200).send(request.params)
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
t.pass()
|
|
80
|
+
} catch (e) {
|
|
81
|
+
t.fail()
|
|
82
|
+
}
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
test('shorthand - get, querystring schema', t => {
|
|
86
|
+
t.plan(1)
|
|
87
|
+
try {
|
|
88
|
+
fastify.route({
|
|
89
|
+
method: 'SEARCH',
|
|
90
|
+
url: '/query',
|
|
91
|
+
querySchema,
|
|
92
|
+
handler: function (request, reply) {
|
|
93
|
+
reply.code(200).send(request.query)
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
t.pass()
|
|
97
|
+
} catch (e) {
|
|
98
|
+
t.fail()
|
|
99
|
+
}
|
|
100
|
+
})
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const t = require('tap')
|
|
4
|
+
const test = t.test
|
|
5
|
+
const fastify = require('..')()
|
|
6
|
+
|
|
7
|
+
test('shorthand - trace', t => {
|
|
8
|
+
t.plan(1)
|
|
9
|
+
try {
|
|
10
|
+
fastify.route({
|
|
11
|
+
method: 'TRACE',
|
|
12
|
+
url: '/',
|
|
13
|
+
handler: function (request, reply) {
|
|
14
|
+
reply.code(200).send('TRACE OK')
|
|
15
|
+
}
|
|
16
|
+
})
|
|
17
|
+
t.pass()
|
|
18
|
+
} catch (e) {
|
|
19
|
+
t.fail()
|
|
20
|
+
}
|
|
21
|
+
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { expectError, expectType } from 'tsd'
|
|
1
|
+
import { expectDeprecated, expectError, expectType } from 'tsd'
|
|
2
2
|
import fastify, {
|
|
3
3
|
FastifyLogFn,
|
|
4
4
|
LogLevel,
|
|
@@ -24,13 +24,10 @@ class Foo {}
|
|
|
24
24
|
expectType<void>(fastify<Server, IncomingMessage, ServerResponse, FastifyLoggerInstance>().log[logLevel as LogLevel](new Foo()))
|
|
25
25
|
})
|
|
26
26
|
|
|
27
|
-
/*
|
|
28
|
-
// TODO make pino export BaseLogger again
|
|
29
27
|
interface CustomLogger extends FastifyBaseLogger {
|
|
30
28
|
customMethod(msg: string, ...args: unknown[]): void;
|
|
31
29
|
}
|
|
32
30
|
|
|
33
|
-
// // ToDo https://github.com/pinojs/pino/issues/1100
|
|
34
31
|
class CustomLoggerImpl implements CustomLogger {
|
|
35
32
|
level = 'info'
|
|
36
33
|
customMethod (msg: string, ...args: unknown[]) { console.log(msg, args) }
|
|
@@ -60,7 +57,6 @@ CustomLoggerImpl
|
|
|
60
57
|
>({ logger: customLogger })
|
|
61
58
|
|
|
62
59
|
expectType<CustomLoggerImpl>(serverWithCustomLogger.log)
|
|
63
|
-
*/
|
|
64
60
|
|
|
65
61
|
const serverWithPino = fastify<
|
|
66
62
|
Server,
|
|
@@ -213,6 +209,9 @@ const passPinoOption = fastify({
|
|
|
213
209
|
|
|
214
210
|
expectType<FastifyBaseLogger>(passPinoOption.log)
|
|
215
211
|
|
|
212
|
+
// FastifyLoggerInstance is deprecated
|
|
213
|
+
expectDeprecated({} as FastifyLoggerInstance)
|
|
214
|
+
|
|
216
215
|
const childParent = fastify().log
|
|
217
216
|
// we test different option variant here
|
|
218
217
|
expectType<FastifyLoggerInstance>(childParent.child({}, { level: 'info' }))
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { expectType, expectError } from 'tsd'
|
|
1
|
+
import { expectType, expectError, expectAssignable } from 'tsd'
|
|
2
2
|
import fastify, { RouteHandlerMethod, RouteHandler, RawRequestDefaultExpression, FastifyContext, FastifyContextConfig, FastifyRequest, FastifyReply } from '../../fastify'
|
|
3
3
|
import { RawServerDefault, RawReplyDefaultExpression, ContextConfigDefault } from '../../types/utils'
|
|
4
4
|
import { FastifyLoggerInstance } from '../../types/logger'
|
|
@@ -6,6 +6,8 @@ import { RouteGenericInterface } from '../../types/route'
|
|
|
6
6
|
import { FastifyInstance } from '../../types/instance'
|
|
7
7
|
import { Buffer } from 'buffer'
|
|
8
8
|
|
|
9
|
+
type DefaultSerializationFunction = (payload: {[key: string]: unknown}) => string
|
|
10
|
+
|
|
9
11
|
const getHandler: RouteHandlerMethod = function (_request, reply) {
|
|
10
12
|
expectType<RawReplyDefaultExpression>(reply.raw)
|
|
11
13
|
expectType<FastifyContext<ContextConfigDefault>>(reply.context)
|
|
@@ -19,7 +21,7 @@ const getHandler: RouteHandlerMethod = function (_request, reply) {
|
|
|
19
21
|
expectType<((payload?: unknown) => FastifyReply)>(reply.send)
|
|
20
22
|
expectType<(key: string, value: any) => FastifyReply>(reply.header)
|
|
21
23
|
expectType<(values: {[key: string]: any}) => FastifyReply>(reply.headers)
|
|
22
|
-
expectType<(key: string) => string | undefined>(reply.getHeader)
|
|
24
|
+
expectType<(key: string) => number | string | string[] | undefined>(reply.getHeader)
|
|
23
25
|
expectType<() => { [key: string]: number | string | string[] | undefined }>(reply.getHeaders)
|
|
24
26
|
expectType<(key: string) => void>(reply.removeHeader)
|
|
25
27
|
expectType<(key: string) => boolean>(reply.hasHeader)
|
|
@@ -32,6 +34,11 @@ const getHandler: RouteHandlerMethod = function (_request, reply) {
|
|
|
32
34
|
expectType<(payload: any) => string | ArrayBuffer | Buffer>(reply.serialize)
|
|
33
35
|
expectType<(fulfilled: () => void, rejected: (err: Error) => void) => void>(reply.then)
|
|
34
36
|
expectType<FastifyInstance>(reply.server)
|
|
37
|
+
expectAssignable<((httpStatus: string) => DefaultSerializationFunction)>(reply.getSerializationFunction)
|
|
38
|
+
expectAssignable<((schema: {[key: string]: unknown}) => DefaultSerializationFunction)>(reply.getSerializationFunction)
|
|
39
|
+
expectAssignable<((schema: {[key: string]: unknown}, httpStatus?: string) => DefaultSerializationFunction)>(reply.compileSerializationSchema)
|
|
40
|
+
expectAssignable<((input: {[key: string]: unknown}, schema: {[key: string]: unknown}, httpStatus?: string) => unknown)>(reply.serializeInput)
|
|
41
|
+
expectAssignable<((input: {[key: string]: unknown}, httpStatus: string) => unknown)>(reply.serializeInput)
|
|
35
42
|
}
|
|
36
43
|
|
|
37
44
|
interface ReplyPayload {
|
|
@@ -40,6 +47,14 @@ interface ReplyPayload {
|
|
|
40
47
|
};
|
|
41
48
|
}
|
|
42
49
|
|
|
50
|
+
interface ReplyUnion {
|
|
51
|
+
Reply: {
|
|
52
|
+
success: boolean;
|
|
53
|
+
} | {
|
|
54
|
+
error: string;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
43
58
|
const typedHandler: RouteHandler<ReplyPayload> = async (request, reply) => {
|
|
44
59
|
expectType<((payload?: ReplyPayload['Reply']) => FastifyReply<RawServerDefault, RawRequestDefaultExpression<RawServerDefault>, RawReplyDefaultExpression<RawServerDefault>, ReplyPayload>)>(reply.send)
|
|
45
60
|
}
|
|
@@ -53,9 +68,35 @@ server.get<ReplyPayload>('/get-generic-send', async function handler (request, r
|
|
|
53
68
|
server.get<ReplyPayload>('/get-generic-return', async function handler (request, reply) {
|
|
54
69
|
return { test: false }
|
|
55
70
|
})
|
|
56
|
-
expectError(server.get<ReplyPayload>('/get-generic-
|
|
71
|
+
expectError(server.get<ReplyPayload>('/get-generic-send-error', async function handler (request, reply) {
|
|
57
72
|
reply.send({ foo: 'bar' })
|
|
58
73
|
}))
|
|
59
74
|
expectError(server.get<ReplyPayload>('/get-generic-return-error', async function handler (request, reply) {
|
|
60
75
|
return { foo: 'bar' }
|
|
61
76
|
}))
|
|
77
|
+
server.get<ReplyUnion>('/get-generic-union-send', async function handler (request, reply) {
|
|
78
|
+
if (0 as number === 0) {
|
|
79
|
+
reply.send({ success: true })
|
|
80
|
+
} else {
|
|
81
|
+
reply.send({ error: 'error' })
|
|
82
|
+
}
|
|
83
|
+
})
|
|
84
|
+
server.get<ReplyUnion>('/get-generic-union-return', async function handler (request, reply) {
|
|
85
|
+
if (0 as number === 0) {
|
|
86
|
+
return { success: true }
|
|
87
|
+
} else {
|
|
88
|
+
return { error: 'error' }
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
expectError(server.get<ReplyUnion>('/get-generic-union-send-error-1', async function handler (request, reply) {
|
|
92
|
+
reply.send({ successes: true })
|
|
93
|
+
}))
|
|
94
|
+
expectError(server.get<ReplyUnion>('/get-generic-union-send-error-2', async function handler (request, reply) {
|
|
95
|
+
reply.send({ error: 500 })
|
|
96
|
+
}))
|
|
97
|
+
expectError(server.get<ReplyUnion>('/get-generic-union-return-error-1', async function handler (request, reply) {
|
|
98
|
+
return { successes: true }
|
|
99
|
+
}))
|
|
100
|
+
expectError(server.get<ReplyUnion>('/get-generic-union-return-error-2', async function handler (request, reply) {
|
|
101
|
+
return { error: 500 }
|
|
102
|
+
}))
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { expectType } from 'tsd'
|
|
1
|
+
import { expectAssignable, expectType } from 'tsd'
|
|
2
2
|
import pino from 'pino'
|
|
3
3
|
import fastify, {
|
|
4
4
|
RouteHandler,
|
|
@@ -21,7 +21,6 @@ import { FastifyRequest } from '../../types/request'
|
|
|
21
21
|
import { FastifyReply } from '../../types/reply'
|
|
22
22
|
import { FastifyInstance } from '../../types/instance'
|
|
23
23
|
import { RouteGenericInterface } from '../../types/route'
|
|
24
|
-
import { ResolveFastifyReplyReturnType, ResolveFastifyRequestType } from '../../types/type-provider'
|
|
25
24
|
|
|
26
25
|
interface RequestBody {
|
|
27
26
|
content: string;
|
|
@@ -55,6 +54,9 @@ type CustomRequest = FastifyRequest<{
|
|
|
55
54
|
Headers: RequestHeaders;
|
|
56
55
|
}>
|
|
57
56
|
|
|
57
|
+
type HTTPRequestPart = 'body' | 'query' | 'querystring' | 'params' | 'headers'
|
|
58
|
+
type ExpectedGetValidationFunction = (input: {[key: string]: unknown}) => boolean
|
|
59
|
+
|
|
58
60
|
interface CustomLoggerInterface extends FastifyLoggerInstance {
|
|
59
61
|
foo: FastifyLogFn; // custom severity logger method
|
|
60
62
|
}
|
|
@@ -83,6 +85,10 @@ const getHandler: RouteHandler = function (request, _reply) {
|
|
|
83
85
|
expectType<RawRequestDefaultExpression['socket']>(request.socket)
|
|
84
86
|
expectType<Error & { validation: any; validationContext: string } | undefined>(request.validationError)
|
|
85
87
|
expectType<FastifyInstance>(request.server)
|
|
88
|
+
expectAssignable<(httpPart: HTTPRequestPart) => ExpectedGetValidationFunction>(request.getValidationFunction)
|
|
89
|
+
expectAssignable<(schema: {[key: string]: unknown}) => ExpectedGetValidationFunction>(request.getValidationFunction)
|
|
90
|
+
expectAssignable<(input: {[key: string]: unknown}, schema: {[key: string]: unknown}, httpPart?: HTTPRequestPart) => boolean>(request.validateInput)
|
|
91
|
+
expectAssignable<(input: {[key: string]: unknown}, httpPart?: HTTPRequestPart) => boolean>(request.validateInput)
|
|
86
92
|
}
|
|
87
93
|
|
|
88
94
|
const getHandlerWithCustomLogger: RouteHandlerMethod<RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, RouteGenericInterface, ContextConfigDefault, FastifySchema, FastifyTypeProviderDefault, CustomLoggerInterface> = function (request, _reply) {
|
|
@@ -128,17 +134,6 @@ server.put('/put', putHandler)
|
|
|
128
134
|
|
|
129
135
|
const customLogger: CustomLoggerInterface = {
|
|
130
136
|
level: 'info',
|
|
131
|
-
version: '5.0',
|
|
132
|
-
useOnlyCustomLevels: false,
|
|
133
|
-
useLevelLabels: false,
|
|
134
|
-
levels: { labels: [], values: {} },
|
|
135
|
-
eventNames: () => [],
|
|
136
|
-
listenerCount: (eventName: string | symbol) => 0,
|
|
137
|
-
bindings: () => ({}),
|
|
138
|
-
flush: () => () => {},
|
|
139
|
-
customLevels: { foo: 1 },
|
|
140
|
-
isLevelEnabled: () => false,
|
|
141
|
-
levelVal: 0,
|
|
142
137
|
silent: () => { },
|
|
143
138
|
info: () => { },
|
|
144
139
|
warn: () => { },
|
|
@@ -147,21 +142,7 @@ const customLogger: CustomLoggerInterface = {
|
|
|
147
142
|
trace: () => { },
|
|
148
143
|
debug: () => { },
|
|
149
144
|
foo: () => { }, // custom severity logger method
|
|
150
|
-
|
|
151
|
-
emit: (event, listener) => false,
|
|
152
|
-
off: (event, listener) => customLogger,
|
|
153
|
-
addListener: (event, listener) => customLogger,
|
|
154
|
-
prependListener: (event, listener) => customLogger,
|
|
155
|
-
prependOnceListener: (event, listener) => customLogger,
|
|
156
|
-
removeListener: (event, listener) => customLogger,
|
|
157
|
-
removeAllListeners: (event) => customLogger,
|
|
158
|
-
setMaxListeners: (n) => customLogger,
|
|
159
|
-
getMaxListeners: () => 0,
|
|
160
|
-
listeners: () => [],
|
|
161
|
-
rawListeners: () => [],
|
|
162
|
-
once: (event, listener) => customLogger,
|
|
163
|
-
child: () => customLogger as pino.Logger<never>,
|
|
164
|
-
setBindings: (bindings) => { }
|
|
145
|
+
child: () => customLogger as pino.Logger<never>
|
|
165
146
|
}
|
|
166
147
|
|
|
167
148
|
const serverWithCustomLogger = fastify({ logger: customLogger })
|
|
@@ -391,7 +391,9 @@ expectError(server.withTypeProvider<JsonSchemaToTsProvider>().get(
|
|
|
391
391
|
// https://github.com/fastify/fastify/issues/4088
|
|
392
392
|
expectError(server.withTypeProvider<JsonSchemaToTsProvider>().get('/', {
|
|
393
393
|
schema: {
|
|
394
|
-
response: {
|
|
394
|
+
response: {
|
|
395
|
+
200: { type: 'string' }
|
|
396
|
+
}
|
|
395
397
|
} as const
|
|
396
398
|
}, (_, res) => {
|
|
397
399
|
return { foo: 555 }
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const t = require('tap')
|
|
4
|
+
const test = t.test
|
|
5
|
+
const sget = require('simple-get').concat
|
|
6
|
+
const fastify = require('..')()
|
|
7
|
+
|
|
8
|
+
test('can be created - unlock', t => {
|
|
9
|
+
t.plan(1)
|
|
10
|
+
try {
|
|
11
|
+
fastify.route({
|
|
12
|
+
method: 'UNLOCK',
|
|
13
|
+
url: '*',
|
|
14
|
+
handler: function (req, reply) {
|
|
15
|
+
reply.code(204).send()
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
t.pass()
|
|
19
|
+
} catch (e) {
|
|
20
|
+
t.fail()
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
fastify.listen({ port: 0 }, err => {
|
|
25
|
+
t.error(err)
|
|
26
|
+
t.teardown(() => { fastify.close() })
|
|
27
|
+
|
|
28
|
+
test('request - unlock', t => {
|
|
29
|
+
t.plan(2)
|
|
30
|
+
sget({
|
|
31
|
+
url: `http://localhost:${fastify.server.address().port}/test/a.txt`,
|
|
32
|
+
method: 'UNLOCK',
|
|
33
|
+
headers: {
|
|
34
|
+
'Lock-Token': 'urn:uuid:a515cfa4-5da4-22e1-f5b5-00a0451e6bf7'
|
|
35
|
+
}
|
|
36
|
+
}, (err, response, body) => {
|
|
37
|
+
t.error(err)
|
|
38
|
+
t.equal(response.statusCode, 204)
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
})
|
package/types/logger.d.ts
CHANGED
|
@@ -19,13 +19,16 @@ export type Bindings = pino.Bindings
|
|
|
19
19
|
|
|
20
20
|
export type ChildLoggerOptions = pino.ChildLoggerOptions
|
|
21
21
|
|
|
22
|
-
export type
|
|
23
|
-
// TODO make pino export BaseLogger again
|
|
24
|
-
// export type FastifyBaseLogger = pino.BaseLogger & {
|
|
25
|
-
export type FastifyBaseLogger = pino.Logger & {
|
|
22
|
+
export type FastifyBaseLogger = pino.BaseLogger & {
|
|
26
23
|
child(bindings: Bindings, options?: ChildLoggerOptions): FastifyBaseLogger
|
|
27
24
|
}
|
|
28
25
|
|
|
26
|
+
// TODO delete FastifyLoggerInstance in the next major release. It seems that it is enough to have only FastifyBaseLogger.
|
|
27
|
+
/**
|
|
28
|
+
* @deprecated Use FastifyBaseLogger instead
|
|
29
|
+
*/
|
|
30
|
+
export type FastifyLoggerInstance = FastifyBaseLogger
|
|
31
|
+
|
|
29
32
|
export interface FastifyLoggerStreamDestination {
|
|
30
33
|
write(msg: string): void;
|
|
31
34
|
}
|
package/types/reply.d.ts
CHANGED
|
@@ -38,7 +38,7 @@ export interface FastifyReply<
|
|
|
38
38
|
send(payload?: ReplyType): FastifyReply<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider>;
|
|
39
39
|
header(key: string, value: any): FastifyReply<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider>;
|
|
40
40
|
headers(values: {[key: string]: any}): FastifyReply<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider>;
|
|
41
|
-
getHeader(key: string): string | undefined;
|
|
41
|
+
getHeader(key: string): number | string | string[] | undefined;
|
|
42
42
|
getHeaders(): {
|
|
43
43
|
// Node's `getHeaders()` can return numbers and arrays, so they're included here as possible types.
|
|
44
44
|
[key: string]: number | string | string[] | undefined;
|
|
@@ -54,10 +54,11 @@ export interface FastifyReply<
|
|
|
54
54
|
type(contentType: string): FastifyReply<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider>;
|
|
55
55
|
serializer(fn: (payload: any) => string): FastifyReply<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider>;
|
|
56
56
|
serialize(payload: any): string | ArrayBuffer | Buffer;
|
|
57
|
-
|
|
58
|
-
getSerializationFunction(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
serializeInput(input:
|
|
57
|
+
// Serialization Methods
|
|
58
|
+
getSerializationFunction(httpStatus: string): (payload: {[key: string]: unknown}) => string;
|
|
59
|
+
getSerializationFunction(schema: {[key: string]: unknown}): (payload: {[key: string]: unknown}) => string;
|
|
60
|
+
compileSerializationSchema(schema: {[key: string]: unknown}, httpStatus?: string): (payload: {[key: string]: unknown}) => string;
|
|
61
|
+
serializeInput(input: {[key: string]: unknown}, schema: {[key: string]: unknown}, httpStatus?: string): string;
|
|
62
|
+
serializeInput(input: {[key: string]: unknown}, httpStatus: string): unknown;
|
|
62
63
|
then(fulfilled: () => void, rejected: (err: Error) => void): void;
|
|
63
64
|
}
|
package/types/request.d.ts
CHANGED
|
@@ -64,8 +64,8 @@ export interface FastifyRequest<RouteGeneric extends RouteGenericInterface = Rou
|
|
|
64
64
|
getValidationFunction(httpPart: HTTPRequestPart): (input: any) => boolean
|
|
65
65
|
getValidationFunction(schema: {[key: string]: any}): (input: any) => boolean
|
|
66
66
|
compileValidationSchema(schema: {[key: string]: any}, httpPart?: HTTPRequestPart): (input: any) => boolean
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
validateInput(input: any, schema: {[key: string]: any}, httpPart?: HTTPRequestPart): boolean
|
|
68
|
+
validateInput(input: any, httpPart?: HTTPRequestPart): boolean
|
|
69
69
|
|
|
70
70
|
// Prefer `socket` over deprecated `connection` property in node 13.0.0 or higher
|
|
71
71
|
// @deprecated
|
package/types/type-provider.d.ts
CHANGED
|
@@ -60,15 +60,6 @@ export interface ResolveFastifyRequestType<TypeProvider extends FastifyTypeProvi
|
|
|
60
60
|
// FastifyReplyType
|
|
61
61
|
// -----------------------------------------------------------------------------------------------
|
|
62
62
|
|
|
63
|
-
// Tests if the user has specified a generic argument for Reply
|
|
64
|
-
type UseReplyFromRouteGeneric<RouteGeneric extends RouteGenericInterface> = keyof RouteGeneric['Reply'] extends never ? false : true
|
|
65
|
-
|
|
66
|
-
// Tests if the user has specified a response schema.
|
|
67
|
-
type UseReplyFromSchemaCompiler<SchemaCompiler extends FastifySchema> = keyof SchemaCompiler['response'] extends never ? false : true
|
|
68
|
-
|
|
69
|
-
// Resolves the Reply type from the generic argument
|
|
70
|
-
type ResolveReplyFromRouteGeneric<RouteGeneric extends RouteGenericInterface> = RouteGeneric['Reply']
|
|
71
|
-
|
|
72
63
|
// Resolves the Reply type by taking a union of response status codes
|
|
73
64
|
type ResolveReplyFromSchemaCompiler<TypeProvider extends FastifyTypeProvider, SchemaCompiler extends FastifySchema> = {
|
|
74
65
|
[K in keyof SchemaCompiler['response']]: CallTypeProvider<TypeProvider, SchemaCompiler['response'][K]>
|
|
@@ -80,11 +71,7 @@ export type FastifyReplyType<Reply = unknown> = Reply
|
|
|
80
71
|
// Resolves the Reply type either via generic argument or from response schema. This type uses a different
|
|
81
72
|
// resolution strategy to Requests where the Reply will infer a union of each status code type specified
|
|
82
73
|
// by the user. The Reply can be explicitly overriden by users providing a generic Reply type on the route.
|
|
83
|
-
export type ResolveFastifyReplyType<TypeProvider extends FastifyTypeProvider, SchemaCompiler extends FastifySchema, RouteGeneric extends RouteGenericInterface> =
|
|
84
|
-
UseReplyFromRouteGeneric<RouteGeneric> extends true ? ResolveReplyFromRouteGeneric<RouteGeneric> :
|
|
85
|
-
UseReplyFromSchemaCompiler<SchemaCompiler> extends true ? ResolveReplyFromSchemaCompiler<TypeProvider, SchemaCompiler> :
|
|
86
|
-
unknown
|
|
87
|
-
>
|
|
74
|
+
export type ResolveFastifyReplyType<TypeProvider extends FastifyTypeProvider, SchemaCompiler extends FastifySchema, RouteGeneric extends RouteGenericInterface> = UndefinedToUnknown<KeysOf<RouteGeneric['Reply']> extends never ? ResolveReplyFromSchemaCompiler<TypeProvider, SchemaCompiler> : RouteGeneric['Reply']>
|
|
88
75
|
|
|
89
76
|
// -----------------------------------------------------------------------------------------------
|
|
90
77
|
// FastifyReplyReturnType
|
package/types/utils.d.ts
CHANGED
|
@@ -5,7 +5,8 @@ import * as https from 'https'
|
|
|
5
5
|
/**
|
|
6
6
|
* Standard HTTP method strings
|
|
7
7
|
*/
|
|
8
|
-
export type HTTPMethods = 'DELETE' | 'GET' | 'HEAD' | 'PATCH' | 'POST' | 'PUT' | 'OPTIONS'
|
|
8
|
+
export type HTTPMethods = 'DELETE' | 'GET' | 'HEAD' | 'PATCH' | 'POST' | 'PUT' | 'OPTIONS' |
|
|
9
|
+
'PROPFIND' | 'PROPPATCH' | 'MKCOL' | 'COPY' | 'MOVE' | 'LOCK' | 'UNLOCK' | 'TRACE' | 'SEARCH'
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* A union type of the Node.js server types from the http, https, and http2 modules.
|