fastify 4.3.0 → 4.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/build-validation.js +1 -1
- package/docs/Guides/Ecosystem.md +23 -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 +6 -3
- package/docs/Reference/Server.md +20 -7
- package/docs/Reference/Validation-and-Serialization.md +1 -1
- package/fastify.d.ts +1 -1
- package/fastify.js +4 -4
- package/lib/configValidator.js +68 -19
- package/lib/context.js +1 -0
- package/lib/handleRequest.js +2 -2
- package/lib/httpMethods.js +22 -0
- package/lib/reqIdGenFactory.js +13 -2
- package/lib/route.js +2 -4
- package/lib/server.js +1 -0
- package/package.json +3 -9
- package/test/copy.test.js +41 -0
- package/test/hooks-async.test.js +43 -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/logger.test.js +108 -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/schema-examples.test.js +54 -0
- package/test/search.test.js +100 -0
- package/test/trace.test.js +21 -0
- package/test/types/fastify.test-d.ts +1 -0
- package/test/types/instance.test-d.ts +1 -1
- 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/test/upgrade.test.js +53 -0
- package/types/instance.d.ts +1 -1
- 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
|
@@ -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
|
+
})
|
package/test/hooks-async.test.js
CHANGED
|
@@ -710,3 +710,46 @@ test('preSerializationEnd should handle errors if the serialize method throws',
|
|
|
710
710
|
|
|
711
711
|
t.end()
|
|
712
712
|
})
|
|
713
|
+
|
|
714
|
+
t.test('nested hooks to do not crash on 404', t => {
|
|
715
|
+
t.plan(2)
|
|
716
|
+
const fastify = Fastify()
|
|
717
|
+
|
|
718
|
+
fastify.get('/hello', (req, reply) => {
|
|
719
|
+
reply.send({ hello: 'world' })
|
|
720
|
+
})
|
|
721
|
+
|
|
722
|
+
fastify.register(async function (fastify) {
|
|
723
|
+
fastify.get('/something', (req, reply) => {
|
|
724
|
+
reply.callNotFound()
|
|
725
|
+
})
|
|
726
|
+
|
|
727
|
+
fastify.setNotFoundHandler(async (request, reply) => {
|
|
728
|
+
reply.statusCode = 404
|
|
729
|
+
return { status: 'nested-not-found' }
|
|
730
|
+
})
|
|
731
|
+
|
|
732
|
+
fastify.setErrorHandler(async (error, request, reply) => {
|
|
733
|
+
reply.statusCode = 500
|
|
734
|
+
return { status: 'nested-error', error }
|
|
735
|
+
})
|
|
736
|
+
}, { prefix: '/nested' })
|
|
737
|
+
|
|
738
|
+
fastify.setNotFoundHandler(async (request, reply) => {
|
|
739
|
+
reply.statusCode = 404
|
|
740
|
+
return { status: 'not-found' }
|
|
741
|
+
})
|
|
742
|
+
|
|
743
|
+
fastify.setErrorHandler(async (error, request, reply) => {
|
|
744
|
+
reply.statusCode = 500
|
|
745
|
+
return { status: 'error', error }
|
|
746
|
+
})
|
|
747
|
+
|
|
748
|
+
fastify.inject({
|
|
749
|
+
method: 'GET',
|
|
750
|
+
url: '/nested/something'
|
|
751
|
+
}, (err, res) => {
|
|
752
|
+
t.error(err)
|
|
753
|
+
t.equal(res.statusCode, 404)
|
|
754
|
+
})
|
|
755
|
+
})
|
|
@@ -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
|
+
})
|
package/test/logger.test.js
CHANGED
|
@@ -330,6 +330,51 @@ test('The request id header key can be customized', t => {
|
|
|
330
330
|
})
|
|
331
331
|
})
|
|
332
332
|
|
|
333
|
+
test('The request id header key can be ignored', t => {
|
|
334
|
+
t.plan(9)
|
|
335
|
+
const REQUEST_ID = 'ignore-me'
|
|
336
|
+
|
|
337
|
+
const stream = split(JSON.parse)
|
|
338
|
+
const fastify = Fastify({
|
|
339
|
+
logger: { stream, level: 'info' },
|
|
340
|
+
requestIdHeader: false
|
|
341
|
+
})
|
|
342
|
+
t.teardown(() => fastify.close())
|
|
343
|
+
|
|
344
|
+
fastify.get('/', (req, reply) => {
|
|
345
|
+
t.equal(req.id, 'req-1')
|
|
346
|
+
req.log.info('some log message')
|
|
347
|
+
reply.send({ id: req.id })
|
|
348
|
+
})
|
|
349
|
+
|
|
350
|
+
fastify.inject({
|
|
351
|
+
method: 'GET',
|
|
352
|
+
url: '/',
|
|
353
|
+
headers: {
|
|
354
|
+
'request-id': REQUEST_ID
|
|
355
|
+
}
|
|
356
|
+
}, (err, res) => {
|
|
357
|
+
t.error(err)
|
|
358
|
+
const payload = JSON.parse(res.payload)
|
|
359
|
+
t.equal(payload.id, 'req-1')
|
|
360
|
+
|
|
361
|
+
stream.once('data', line => {
|
|
362
|
+
t.equal(line.reqId, 'req-1')
|
|
363
|
+
t.equal(line.msg, 'incoming request', 'message is set')
|
|
364
|
+
|
|
365
|
+
stream.once('data', line => {
|
|
366
|
+
t.equal(line.reqId, 'req-1')
|
|
367
|
+
t.equal(line.msg, 'some log message', 'message is set')
|
|
368
|
+
|
|
369
|
+
stream.once('data', line => {
|
|
370
|
+
t.equal(line.reqId, 'req-1')
|
|
371
|
+
t.equal(line.msg, 'request completed', 'message is set')
|
|
372
|
+
})
|
|
373
|
+
})
|
|
374
|
+
})
|
|
375
|
+
})
|
|
376
|
+
})
|
|
377
|
+
|
|
333
378
|
test('The request id header key can be customized along with a custom id generator', t => {
|
|
334
379
|
t.plan(12)
|
|
335
380
|
const REQUEST_ID = '42'
|
|
@@ -393,6 +438,69 @@ test('The request id header key can be customized along with a custom id generat
|
|
|
393
438
|
})
|
|
394
439
|
})
|
|
395
440
|
|
|
441
|
+
test('The request id header key can be ignored along with a custom id generator', t => {
|
|
442
|
+
t.plan(12)
|
|
443
|
+
const REQUEST_ID = 'ignore-me'
|
|
444
|
+
|
|
445
|
+
const stream = split(JSON.parse)
|
|
446
|
+
const fastify = Fastify({
|
|
447
|
+
logger: { stream, level: 'info' },
|
|
448
|
+
requestIdHeader: false,
|
|
449
|
+
genReqId (req) {
|
|
450
|
+
return 'foo'
|
|
451
|
+
}
|
|
452
|
+
})
|
|
453
|
+
t.teardown(() => fastify.close())
|
|
454
|
+
|
|
455
|
+
fastify.get('/one', (req, reply) => {
|
|
456
|
+
t.equal(req.id, 'foo')
|
|
457
|
+
req.log.info('some log message')
|
|
458
|
+
reply.send({ id: req.id })
|
|
459
|
+
})
|
|
460
|
+
|
|
461
|
+
fastify.get('/two', (req, reply) => {
|
|
462
|
+
t.equal(req.id, 'foo')
|
|
463
|
+
req.log.info('some log message 2')
|
|
464
|
+
reply.send({ id: req.id })
|
|
465
|
+
})
|
|
466
|
+
|
|
467
|
+
const matches = [
|
|
468
|
+
{ reqId: 'foo', msg: /incoming request/ },
|
|
469
|
+
{ reqId: 'foo', msg: /some log message/ },
|
|
470
|
+
{ reqId: 'foo', msg: /request completed/ },
|
|
471
|
+
{ reqId: 'foo', msg: /incoming request/ },
|
|
472
|
+
{ reqId: 'foo', msg: /some log message 2/ },
|
|
473
|
+
{ reqId: 'foo', msg: /request completed/ }
|
|
474
|
+
]
|
|
475
|
+
|
|
476
|
+
let i = 0
|
|
477
|
+
stream.on('data', line => {
|
|
478
|
+
t.match(line, matches[i])
|
|
479
|
+
i += 1
|
|
480
|
+
})
|
|
481
|
+
|
|
482
|
+
fastify.inject({
|
|
483
|
+
method: 'GET',
|
|
484
|
+
url: '/one',
|
|
485
|
+
headers: {
|
|
486
|
+
'request-id': REQUEST_ID
|
|
487
|
+
}
|
|
488
|
+
}, (err, res) => {
|
|
489
|
+
t.error(err)
|
|
490
|
+
const payload = JSON.parse(res.payload)
|
|
491
|
+
t.equal(payload.id, 'foo')
|
|
492
|
+
})
|
|
493
|
+
|
|
494
|
+
fastify.inject({
|
|
495
|
+
method: 'GET',
|
|
496
|
+
url: '/two'
|
|
497
|
+
}, (err, res) => {
|
|
498
|
+
t.error(err)
|
|
499
|
+
const payload = JSON.parse(res.payload)
|
|
500
|
+
t.equal(payload.id, 'foo')
|
|
501
|
+
})
|
|
502
|
+
})
|
|
503
|
+
|
|
396
504
|
test('The request id log label can be changed', t => {
|
|
397
505
|
t.plan(6)
|
|
398
506
|
const REQUEST_ID = '42'
|
|
@@ -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
|
+
})
|
|
@@ -509,6 +509,60 @@ test('should return custom error messages with ajv-errors', t => {
|
|
|
509
509
|
})
|
|
510
510
|
})
|
|
511
511
|
|
|
512
|
+
test('should be able to handle formats of ajv-formats when added by plugins option', t => {
|
|
513
|
+
t.plan(3)
|
|
514
|
+
|
|
515
|
+
const fastify = Fastify({
|
|
516
|
+
ajv: {
|
|
517
|
+
plugins: [
|
|
518
|
+
require('ajv-formats')
|
|
519
|
+
]
|
|
520
|
+
}
|
|
521
|
+
})
|
|
522
|
+
|
|
523
|
+
const schema = {
|
|
524
|
+
body: {
|
|
525
|
+
type: 'object',
|
|
526
|
+
properties: {
|
|
527
|
+
id: { type: 'string', format: 'uuid' },
|
|
528
|
+
email: { type: 'string', format: 'email' }
|
|
529
|
+
},
|
|
530
|
+
required: ['id', 'email']
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
fastify.post('/', { schema }, function (req, reply) {
|
|
535
|
+
reply.code(200).send(req.body.id)
|
|
536
|
+
})
|
|
537
|
+
|
|
538
|
+
fastify.inject({
|
|
539
|
+
method: 'POST',
|
|
540
|
+
payload: {
|
|
541
|
+
id: '254381a5-888c-4b41-8116-e3b1a54980bd',
|
|
542
|
+
email: 'info@fastify.io'
|
|
543
|
+
},
|
|
544
|
+
url: '/'
|
|
545
|
+
}, (_err, res) => {
|
|
546
|
+
t.equal(res.body, '254381a5-888c-4b41-8116-e3b1a54980bd')
|
|
547
|
+
t.equal(res.statusCode, 200)
|
|
548
|
+
})
|
|
549
|
+
|
|
550
|
+
fastify.inject({
|
|
551
|
+
method: 'POST',
|
|
552
|
+
payload: {
|
|
553
|
+
id: 'invalid',
|
|
554
|
+
email: 'info@fastify.io'
|
|
555
|
+
},
|
|
556
|
+
url: '/'
|
|
557
|
+
}, (_err, res) => {
|
|
558
|
+
t.same(JSON.parse(res.payload), {
|
|
559
|
+
statusCode: 400,
|
|
560
|
+
error: 'Bad Request',
|
|
561
|
+
message: 'body/id must match format "uuid"'
|
|
562
|
+
})
|
|
563
|
+
})
|
|
564
|
+
})
|
|
565
|
+
|
|
512
566
|
test('should return localized error messages with ajv-i18n', t => {
|
|
513
567
|
t.plan(3)
|
|
514
568
|
|