fastify 2.7.1 → 2.11.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/README.md +15 -4
- package/build/build-validation.js +8 -0
- package/docs/Benchmarking.md +2 -2
- package/docs/ContentTypeParser.md +12 -10
- package/docs/Decorators.md +14 -14
- package/docs/Ecosystem.md +7 -1
- package/docs/Errors.md +13 -8
- package/docs/Fluent-Schema.md +9 -12
- package/docs/Getting-Started.md +29 -25
- package/docs/HTTP2.md +1 -1
- package/docs/Hooks.md +201 -186
- package/docs/LTS.md +6 -7
- package/docs/Logging.md +10 -10
- package/docs/Middleware.md +59 -0
- package/docs/Plugins-Guide.md +52 -52
- package/docs/Plugins.md +3 -0
- package/docs/Reply.md +47 -3
- package/docs/Routes.md +120 -8
- package/docs/Server.md +69 -3
- package/docs/Serverless.md +76 -4
- package/docs/TypeScript.md +33 -10
- package/docs/Validation-and-Serialization.md +137 -1
- package/examples/typescript-server.ts +1 -1
- package/fastify.d.ts +52 -13
- package/fastify.js +68 -7
- package/lib/configValidator.js +99 -52
- package/lib/contentTypeParser.js +4 -4
- package/lib/context.js +2 -1
- package/lib/errors.js +21 -18
- package/lib/fourOhFour.js +10 -10
- package/lib/handleRequest.js +1 -2
- package/lib/logger.js +2 -2
- package/lib/pluginUtils.js +32 -0
- package/lib/reply.js +41 -6
- package/lib/route.js +37 -9
- package/lib/schemas.js +23 -12
- package/lib/symbols.js +4 -1
- package/lib/validation.js +15 -9
- package/lib/wrapThenable.js +1 -1
- package/package.json +34 -26
- package/test/404s.test.js +41 -1
- package/test/async-await.js +66 -0
- package/test/custom-parser.test.js +1 -1
- package/test/custom-querystring-parser.test.js +1 -1
- package/test/decorator.test.js +48 -0
- package/test/emit-warning.test.js +3 -3
- package/test/fastify-instance.test.js +29 -0
- package/test/helper.js +7 -7
- package/test/hooks-async.js +4 -3
- package/test/hooks.test.js +27 -8
- package/test/input-validation.test.js +126 -0
- package/test/internals/errors.test.js +9 -1
- package/test/internals/initialConfig.test.js +4 -2
- package/test/internals/plugin.test.js +4 -4
- package/test/internals/reply.test.js +78 -6
- package/test/internals/schemas.test.js +30 -0
- package/test/internals/validation.test.js +18 -0
- package/test/listen.test.js +1 -1
- package/test/logger.test.js +314 -1
- package/test/plugin.test.js +171 -0
- package/test/promises.test.js +55 -0
- package/test/proto-poisoning.test.js +76 -0
- package/test/route-hooks.test.js +109 -91
- package/test/route-prefix.test.js +1 -1
- package/test/schemas.test.js +450 -0
- package/test/shared-schemas.test.js +2 -2
- package/test/stream.test.js +10 -6
- package/test/throw.test.js +48 -2
- package/test/types/index.ts +86 -1
- package/test/validation-error-handling.test.js +3 -3
- package/test/versioned-routes.test.js +1 -1
- package/docs/Middlewares.md +0 -59
package/test/logger.test.js
CHANGED
|
@@ -567,6 +567,40 @@ test('Should set a custom logLevel for a plugin', t => {
|
|
|
567
567
|
})
|
|
568
568
|
})
|
|
569
569
|
|
|
570
|
+
test('Should set a custom logSerializers for a plugin', t => {
|
|
571
|
+
t.plan(3)
|
|
572
|
+
|
|
573
|
+
const splitStream = split(JSON.parse)
|
|
574
|
+
splitStream.on('data', (line) => {
|
|
575
|
+
if (line.test) {
|
|
576
|
+
t.is(line.test, 'XHello')
|
|
577
|
+
}
|
|
578
|
+
})
|
|
579
|
+
|
|
580
|
+
const logger = pino({ level: 'error' }, splitStream)
|
|
581
|
+
|
|
582
|
+
const fastify = Fastify({
|
|
583
|
+
logger
|
|
584
|
+
})
|
|
585
|
+
|
|
586
|
+
fastify.register(function (instance, opts, next) {
|
|
587
|
+
instance.get('/plugin', (req, reply) => {
|
|
588
|
+
req.log.info({ test: 'Hello' }) // we should see this log
|
|
589
|
+
reply.send({ hello: 'world' })
|
|
590
|
+
})
|
|
591
|
+
next()
|
|
592
|
+
}, { logLevel: 'info', logSerializers: { test: value => 'X' + value } })
|
|
593
|
+
|
|
594
|
+
fastify.inject({
|
|
595
|
+
method: 'GET',
|
|
596
|
+
url: '/plugin'
|
|
597
|
+
}, (err, res) => {
|
|
598
|
+
t.error(err)
|
|
599
|
+
const payload = JSON.parse(res.payload)
|
|
600
|
+
t.deepEqual(payload, { hello: 'world' })
|
|
601
|
+
})
|
|
602
|
+
})
|
|
603
|
+
|
|
570
604
|
test('Should set a custom logLevel for every plugin', t => {
|
|
571
605
|
const lines = ['incoming request', 'request completed', 'info', 'debug']
|
|
572
606
|
t.plan(18)
|
|
@@ -634,6 +668,281 @@ test('Should set a custom logLevel for every plugin', t => {
|
|
|
634
668
|
})
|
|
635
669
|
})
|
|
636
670
|
|
|
671
|
+
test('Should set a custom logSerializers for every plugin', t => {
|
|
672
|
+
const lines = ['Hello', 'XHello', 'ZHello']
|
|
673
|
+
t.plan(9)
|
|
674
|
+
|
|
675
|
+
const splitStream = split(JSON.parse)
|
|
676
|
+
splitStream.on('data', (line) => {
|
|
677
|
+
if (line.test) {
|
|
678
|
+
t.is(line.test, lines.shift())
|
|
679
|
+
}
|
|
680
|
+
})
|
|
681
|
+
|
|
682
|
+
const logger = pino({ level: 'info' }, splitStream)
|
|
683
|
+
const fastify = Fastify({
|
|
684
|
+
logger
|
|
685
|
+
})
|
|
686
|
+
|
|
687
|
+
fastify.get('/', (req, reply) => {
|
|
688
|
+
req.log.warn({ test: 'Hello' })
|
|
689
|
+
reply.send({ hello: 'world' })
|
|
690
|
+
})
|
|
691
|
+
|
|
692
|
+
fastify.register(function (instance, opts, next) {
|
|
693
|
+
instance.get('/test1', (req, reply) => {
|
|
694
|
+
req.log.info({ test: 'Hello' })
|
|
695
|
+
reply.send({ hello: 'world' })
|
|
696
|
+
})
|
|
697
|
+
next()
|
|
698
|
+
}, { logSerializers: { test: value => 'X' + value } })
|
|
699
|
+
|
|
700
|
+
fastify.register(function (instance, opts, next) {
|
|
701
|
+
instance.get('/test2', (req, reply) => {
|
|
702
|
+
req.log.info({ test: 'Hello' })
|
|
703
|
+
reply.send({ hello: 'world' })
|
|
704
|
+
})
|
|
705
|
+
next()
|
|
706
|
+
}, { logSerializers: { test: value => 'Z' + value } })
|
|
707
|
+
|
|
708
|
+
fastify.inject({
|
|
709
|
+
method: 'GET',
|
|
710
|
+
url: '/'
|
|
711
|
+
}, (err, res) => {
|
|
712
|
+
t.error(err)
|
|
713
|
+
const payload = JSON.parse(res.payload)
|
|
714
|
+
t.deepEqual(payload, { hello: 'world' })
|
|
715
|
+
})
|
|
716
|
+
|
|
717
|
+
fastify.inject({
|
|
718
|
+
method: 'GET',
|
|
719
|
+
url: '/test1'
|
|
720
|
+
}, (err, res) => {
|
|
721
|
+
t.error(err)
|
|
722
|
+
const payload = JSON.parse(res.payload)
|
|
723
|
+
t.deepEqual(payload, { hello: 'world' })
|
|
724
|
+
})
|
|
725
|
+
|
|
726
|
+
fastify.inject({
|
|
727
|
+
method: 'GET',
|
|
728
|
+
url: '/test2'
|
|
729
|
+
}, (err, res) => {
|
|
730
|
+
t.error(err)
|
|
731
|
+
const payload = JSON.parse(res.payload)
|
|
732
|
+
t.deepEqual(payload, { hello: 'world' })
|
|
733
|
+
})
|
|
734
|
+
})
|
|
735
|
+
|
|
736
|
+
test('Should override serializers from route', t => {
|
|
737
|
+
t.plan(3)
|
|
738
|
+
|
|
739
|
+
const splitStream = split(JSON.parse)
|
|
740
|
+
splitStream.on('data', (line) => {
|
|
741
|
+
if (line.test) {
|
|
742
|
+
t.is(line.test, 'ZHello')
|
|
743
|
+
}
|
|
744
|
+
})
|
|
745
|
+
|
|
746
|
+
const logger = pino({ level: 'info' }, splitStream)
|
|
747
|
+
const fastify = Fastify({
|
|
748
|
+
logger
|
|
749
|
+
})
|
|
750
|
+
|
|
751
|
+
fastify.register(function (instance, opts, next) {
|
|
752
|
+
instance.get('/', {
|
|
753
|
+
logSerializers: {
|
|
754
|
+
test: value => 'Z' + value // should override
|
|
755
|
+
}
|
|
756
|
+
}, (req, reply) => {
|
|
757
|
+
req.log.info({ test: 'Hello' })
|
|
758
|
+
reply.send({ hello: 'world' })
|
|
759
|
+
})
|
|
760
|
+
next()
|
|
761
|
+
}, { logSerializers: { test: value => 'X' + value } })
|
|
762
|
+
|
|
763
|
+
fastify.inject({
|
|
764
|
+
method: 'GET',
|
|
765
|
+
url: '/'
|
|
766
|
+
}, (err, res) => {
|
|
767
|
+
t.error(err)
|
|
768
|
+
const payload = JSON.parse(res.payload)
|
|
769
|
+
t.deepEqual(payload, { hello: 'world' })
|
|
770
|
+
})
|
|
771
|
+
})
|
|
772
|
+
|
|
773
|
+
test('Should override serializers from plugin', t => {
|
|
774
|
+
t.plan(3)
|
|
775
|
+
|
|
776
|
+
const splitStream = split(JSON.parse)
|
|
777
|
+
splitStream.on('data', (line) => {
|
|
778
|
+
if (line.test) {
|
|
779
|
+
t.is(line.test, 'ZHello')
|
|
780
|
+
}
|
|
781
|
+
})
|
|
782
|
+
|
|
783
|
+
const logger = pino({ level: 'info' }, splitStream)
|
|
784
|
+
const fastify = Fastify({
|
|
785
|
+
logger
|
|
786
|
+
})
|
|
787
|
+
|
|
788
|
+
fastify.register(function (instance, opts, next) {
|
|
789
|
+
instance.register(context1, {
|
|
790
|
+
logSerializers: {
|
|
791
|
+
test: value => 'Z' + value // should override
|
|
792
|
+
}
|
|
793
|
+
})
|
|
794
|
+
next()
|
|
795
|
+
}, { logSerializers: { test: value => 'X' + value } })
|
|
796
|
+
|
|
797
|
+
function context1 (instance, opts, next) {
|
|
798
|
+
instance.get('/', (req, reply) => {
|
|
799
|
+
req.log.info({ test: 'Hello' })
|
|
800
|
+
reply.send({ hello: 'world' })
|
|
801
|
+
})
|
|
802
|
+
next()
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
fastify.inject({
|
|
806
|
+
method: 'GET',
|
|
807
|
+
url: '/'
|
|
808
|
+
}, (err, res) => {
|
|
809
|
+
t.error(err)
|
|
810
|
+
const payload = JSON.parse(res.payload)
|
|
811
|
+
t.deepEqual(payload, { hello: 'world' })
|
|
812
|
+
})
|
|
813
|
+
})
|
|
814
|
+
|
|
815
|
+
test('Should use serializers from plugin and route', t => {
|
|
816
|
+
t.plan(4)
|
|
817
|
+
|
|
818
|
+
const splitStream = split(JSON.parse)
|
|
819
|
+
splitStream.on('data', (line) => {
|
|
820
|
+
if (line.test) {
|
|
821
|
+
t.is(line.test, 'XHello')
|
|
822
|
+
}
|
|
823
|
+
if (line.test2) {
|
|
824
|
+
t.is(line.test2, 'ZHello')
|
|
825
|
+
}
|
|
826
|
+
})
|
|
827
|
+
|
|
828
|
+
const logger = pino({ level: 'info' }, splitStream)
|
|
829
|
+
const fastify = Fastify({
|
|
830
|
+
logger
|
|
831
|
+
})
|
|
832
|
+
|
|
833
|
+
fastify.register(context1, {
|
|
834
|
+
logSerializers: { test: value => 'X' + value }
|
|
835
|
+
})
|
|
836
|
+
|
|
837
|
+
function context1 (instance, opts, next) {
|
|
838
|
+
instance.get('/', {
|
|
839
|
+
logSerializers: {
|
|
840
|
+
test2: value => 'Z' + value
|
|
841
|
+
}
|
|
842
|
+
}, (req, reply) => {
|
|
843
|
+
req.log.info({ test: 'Hello', test2: 'Hello' }) // { test: 'XHello', test2: 'ZHello' }
|
|
844
|
+
reply.send({ hello: 'world' })
|
|
845
|
+
})
|
|
846
|
+
next()
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
fastify.inject({
|
|
850
|
+
method: 'GET',
|
|
851
|
+
url: '/'
|
|
852
|
+
}, (err, res) => {
|
|
853
|
+
t.error(err)
|
|
854
|
+
const payload = JSON.parse(res.payload)
|
|
855
|
+
t.deepEqual(payload, { hello: 'world' })
|
|
856
|
+
})
|
|
857
|
+
})
|
|
858
|
+
|
|
859
|
+
test('Should use serializers from instance fastify and route', t => {
|
|
860
|
+
t.plan(4)
|
|
861
|
+
|
|
862
|
+
const splitStream = split(JSON.parse)
|
|
863
|
+
splitStream.on('data', (line) => {
|
|
864
|
+
if (line.test) {
|
|
865
|
+
t.is(line.test, 'XHello')
|
|
866
|
+
}
|
|
867
|
+
if (line.test2) {
|
|
868
|
+
t.is(line.test2, 'ZHello')
|
|
869
|
+
}
|
|
870
|
+
})
|
|
871
|
+
|
|
872
|
+
const logger = pino({
|
|
873
|
+
level: 'info',
|
|
874
|
+
serializers: {
|
|
875
|
+
test: value => 'X' + value,
|
|
876
|
+
test2: value => 'This should be override - ' + value
|
|
877
|
+
}
|
|
878
|
+
}, splitStream)
|
|
879
|
+
const fastify = Fastify({
|
|
880
|
+
logger
|
|
881
|
+
})
|
|
882
|
+
|
|
883
|
+
fastify.get('/', {
|
|
884
|
+
logSerializers: {
|
|
885
|
+
test2: value => 'Z' + value
|
|
886
|
+
}
|
|
887
|
+
}, (req, reply) => {
|
|
888
|
+
req.log.info({ test: 'Hello', test2: 'Hello' }) // { test: 'XHello', test2: 'ZHello' }
|
|
889
|
+
reply.send({ hello: 'world' })
|
|
890
|
+
})
|
|
891
|
+
|
|
892
|
+
fastify.inject({
|
|
893
|
+
method: 'GET',
|
|
894
|
+
url: '/'
|
|
895
|
+
}, (err, res) => {
|
|
896
|
+
t.error(err)
|
|
897
|
+
const payload = JSON.parse(res.payload)
|
|
898
|
+
t.deepEqual(payload, { hello: 'world' })
|
|
899
|
+
})
|
|
900
|
+
})
|
|
901
|
+
|
|
902
|
+
test('Should use serializers inherit from contexts', t => {
|
|
903
|
+
t.plan(5)
|
|
904
|
+
|
|
905
|
+
const splitStream = split(JSON.parse)
|
|
906
|
+
splitStream.on('data', (line) => {
|
|
907
|
+
if (line.test && line.test2 && line.test3) {
|
|
908
|
+
t.is(line.test, 'XHello')
|
|
909
|
+
t.is(line.test2, 'YHello')
|
|
910
|
+
t.is(line.test3, 'ZHello')
|
|
911
|
+
}
|
|
912
|
+
})
|
|
913
|
+
|
|
914
|
+
const logger = pino({
|
|
915
|
+
level: 'info',
|
|
916
|
+
serializers: {
|
|
917
|
+
test: value => 'X' + value
|
|
918
|
+
}
|
|
919
|
+
}, splitStream)
|
|
920
|
+
|
|
921
|
+
const fastify = Fastify({ logger })
|
|
922
|
+
fastify.register(context1, { logSerializers: { test2: value => 'Y' + value } })
|
|
923
|
+
|
|
924
|
+
function context1 (instance, opts, next) {
|
|
925
|
+
instance.get('/', {
|
|
926
|
+
logSerializers: {
|
|
927
|
+
test3: value => 'Z' + value
|
|
928
|
+
}
|
|
929
|
+
}, (req, reply) => {
|
|
930
|
+
req.log.info({ test: 'Hello', test2: 'Hello', test3: 'Hello' }) // { test: 'XHello', test2: 'YHello', test3: 'ZHello' }
|
|
931
|
+
reply.send({ hello: 'world' })
|
|
932
|
+
})
|
|
933
|
+
next()
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
fastify.inject({
|
|
937
|
+
method: 'GET',
|
|
938
|
+
url: '/'
|
|
939
|
+
}, (err, res) => {
|
|
940
|
+
t.error(err)
|
|
941
|
+
const payload = JSON.parse(res.payload)
|
|
942
|
+
t.deepEqual(payload, { hello: 'world' })
|
|
943
|
+
})
|
|
944
|
+
})
|
|
945
|
+
|
|
637
946
|
test('Should increase the log level for a specific plugin', t => {
|
|
638
947
|
t.plan(4)
|
|
639
948
|
|
|
@@ -783,7 +1092,11 @@ test('Should set a custom log level for a specific route', t => {
|
|
|
783
1092
|
test('The default 404 handler logs the incoming request', t => {
|
|
784
1093
|
t.plan(5)
|
|
785
1094
|
|
|
786
|
-
const expectedMessages = [
|
|
1095
|
+
const expectedMessages = [
|
|
1096
|
+
'incoming request',
|
|
1097
|
+
'Route GET:/not-found not found',
|
|
1098
|
+
'request completed'
|
|
1099
|
+
]
|
|
787
1100
|
|
|
788
1101
|
const splitStream = split(JSON.parse)
|
|
789
1102
|
splitStream.on('data', (line) => {
|
package/test/plugin.test.js
CHANGED
|
@@ -18,6 +18,29 @@ test('require a plugin', t => {
|
|
|
18
18
|
})
|
|
19
19
|
})
|
|
20
20
|
|
|
21
|
+
test('plugin metadata - ignore prefix', t => {
|
|
22
|
+
t.plan(2)
|
|
23
|
+
const fastify = Fastify()
|
|
24
|
+
|
|
25
|
+
plugin[Symbol.for('skip-override')] = true
|
|
26
|
+
fastify.register(plugin, { prefix: 'foo' })
|
|
27
|
+
|
|
28
|
+
fastify.inject({
|
|
29
|
+
method: 'GET',
|
|
30
|
+
url: '/'
|
|
31
|
+
}, function (err, res) {
|
|
32
|
+
t.error(err)
|
|
33
|
+
t.equals(res.payload, 'hello')
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
function plugin (instance, opts, next) {
|
|
37
|
+
instance.get('/', function (request, reply) {
|
|
38
|
+
reply.send('hello')
|
|
39
|
+
})
|
|
40
|
+
next()
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
21
44
|
test('fastify.register with fastify-plugin should not incapsulate his code', t => {
|
|
22
45
|
t.plan(10)
|
|
23
46
|
const fastify = Fastify()
|
|
@@ -312,6 +335,154 @@ test('check dependencies - should throw', t => {
|
|
|
312
335
|
})
|
|
313
336
|
})
|
|
314
337
|
|
|
338
|
+
test('set the plugin name based on the plugin displayName symbol', t => {
|
|
339
|
+
t.plan(5)
|
|
340
|
+
const fastify = Fastify()
|
|
341
|
+
|
|
342
|
+
fastify.register(fp((fastify, opts, next) => {
|
|
343
|
+
t.strictEqual(fastify.pluginName, 'plugin-A')
|
|
344
|
+
fastify.register(fp((fastify, opts, next) => {
|
|
345
|
+
t.strictEqual(fastify.pluginName, 'plugin-A -> plugin-AB')
|
|
346
|
+
next()
|
|
347
|
+
}, { name: 'plugin-AB' }))
|
|
348
|
+
fastify.register(fp((fastify, opts, next) => {
|
|
349
|
+
t.strictEqual(fastify.pluginName, 'plugin-A -> plugin-AB -> plugin-AC')
|
|
350
|
+
next()
|
|
351
|
+
}, { name: 'plugin-AC' }))
|
|
352
|
+
next()
|
|
353
|
+
}, { name: 'plugin-A' }))
|
|
354
|
+
|
|
355
|
+
fastify.register(fp((fastify, opts, next) => {
|
|
356
|
+
t.strictEqual(fastify.pluginName, 'plugin-A -> plugin-AB -> plugin-AC -> plugin-B')
|
|
357
|
+
next()
|
|
358
|
+
}, { name: 'plugin-B' }))
|
|
359
|
+
|
|
360
|
+
fastify.listen(0, err => {
|
|
361
|
+
t.error(err)
|
|
362
|
+
fastify.close()
|
|
363
|
+
})
|
|
364
|
+
})
|
|
365
|
+
|
|
366
|
+
test('plugin name will change when using no encapsulation', t => {
|
|
367
|
+
t.plan(5)
|
|
368
|
+
const fastify = Fastify()
|
|
369
|
+
|
|
370
|
+
fastify.register(fp((fastify, opts, next) => {
|
|
371
|
+
// store it in a different variable will hold the correct name
|
|
372
|
+
const pluginName = fastify.pluginName
|
|
373
|
+
fastify.register(fp((fastify, opts, next) => {
|
|
374
|
+
t.strictEqual(fastify.pluginName, 'plugin-A -> plugin-AB')
|
|
375
|
+
next()
|
|
376
|
+
}, { name: 'plugin-AB' }))
|
|
377
|
+
fastify.register(fp((fastify, opts, next) => {
|
|
378
|
+
t.strictEqual(fastify.pluginName, 'plugin-A -> plugin-AB -> plugin-AC')
|
|
379
|
+
next()
|
|
380
|
+
}, { name: 'plugin-AC' }))
|
|
381
|
+
setImmediate(() => {
|
|
382
|
+
// normally we would expect the name plugin-A
|
|
383
|
+
// but we operate on the same instance in each plugin
|
|
384
|
+
t.strictEqual(fastify.pluginName, 'plugin-A -> plugin-AB -> plugin-AC')
|
|
385
|
+
t.strictEqual(pluginName, 'plugin-A')
|
|
386
|
+
})
|
|
387
|
+
next()
|
|
388
|
+
}, { name: 'plugin-A' }))
|
|
389
|
+
|
|
390
|
+
fastify.listen(0, err => {
|
|
391
|
+
t.error(err)
|
|
392
|
+
fastify.close()
|
|
393
|
+
})
|
|
394
|
+
})
|
|
395
|
+
|
|
396
|
+
test('plugin name is undefined when accessing in no plugin context', t => {
|
|
397
|
+
t.plan(2)
|
|
398
|
+
const fastify = Fastify()
|
|
399
|
+
|
|
400
|
+
t.strictEqual(fastify.pluginName, undefined)
|
|
401
|
+
|
|
402
|
+
fastify.listen(0, err => {
|
|
403
|
+
t.error(err)
|
|
404
|
+
fastify.close()
|
|
405
|
+
})
|
|
406
|
+
})
|
|
407
|
+
|
|
408
|
+
test('set the plugin name based on the plugin function name', t => {
|
|
409
|
+
t.plan(5)
|
|
410
|
+
const fastify = Fastify()
|
|
411
|
+
|
|
412
|
+
fastify.register(function myPluginA (fastify, opts, next) {
|
|
413
|
+
t.strictEqual(fastify.pluginName, 'myPluginA')
|
|
414
|
+
fastify.register(function myPluginAB (fastify, opts, next) {
|
|
415
|
+
t.strictEqual(fastify.pluginName, 'myPluginAB')
|
|
416
|
+
next()
|
|
417
|
+
})
|
|
418
|
+
setImmediate(() => {
|
|
419
|
+
// exact name due to encapsulation
|
|
420
|
+
t.strictEqual(fastify.pluginName, 'myPluginA')
|
|
421
|
+
})
|
|
422
|
+
next()
|
|
423
|
+
})
|
|
424
|
+
|
|
425
|
+
fastify.register(function myPluginB (fastify, opts, next) {
|
|
426
|
+
t.strictEqual(fastify.pluginName, 'myPluginB')
|
|
427
|
+
next()
|
|
428
|
+
})
|
|
429
|
+
|
|
430
|
+
fastify.listen(0, err => {
|
|
431
|
+
t.error(err)
|
|
432
|
+
fastify.close()
|
|
433
|
+
})
|
|
434
|
+
})
|
|
435
|
+
|
|
436
|
+
test('approximate a plugin name when no meta data is available', t => {
|
|
437
|
+
t.plan(7)
|
|
438
|
+
const fastify = Fastify()
|
|
439
|
+
|
|
440
|
+
fastify.register((fastify, opts, next) => {
|
|
441
|
+
// A
|
|
442
|
+
t.is(fastify.pluginName.startsWith('(fastify, opts, next)'), true)
|
|
443
|
+
t.is(fastify.pluginName.includes('// A'), true)
|
|
444
|
+
fastify.register((fastify, opts, next) => {
|
|
445
|
+
// B
|
|
446
|
+
t.is(fastify.pluginName.startsWith('(fastify, opts, next)'), true)
|
|
447
|
+
t.is(fastify.pluginName.includes('// B'), true)
|
|
448
|
+
next()
|
|
449
|
+
})
|
|
450
|
+
setImmediate(() => {
|
|
451
|
+
t.is(fastify.pluginName.startsWith('(fastify, opts, next)'), true)
|
|
452
|
+
t.is(fastify.pluginName.includes('// A'), true)
|
|
453
|
+
})
|
|
454
|
+
next()
|
|
455
|
+
})
|
|
456
|
+
|
|
457
|
+
fastify.listen(0, err => {
|
|
458
|
+
t.error(err)
|
|
459
|
+
fastify.close()
|
|
460
|
+
})
|
|
461
|
+
})
|
|
462
|
+
|
|
463
|
+
test('approximate a plugin name also when fastify-plugin has no meta data', t => {
|
|
464
|
+
t.plan(4)
|
|
465
|
+
const fastify = Fastify()
|
|
466
|
+
|
|
467
|
+
fastify.register(fp((fastify, opts, next) => {
|
|
468
|
+
t.is(fastify.pluginName, 'plugin.test')
|
|
469
|
+
fastify.register(fp(function B (fastify, opts, next) {
|
|
470
|
+
// function has name
|
|
471
|
+
t.is(fastify.pluginName, 'plugin.test -> B')
|
|
472
|
+
next()
|
|
473
|
+
}))
|
|
474
|
+
setImmediate(() => {
|
|
475
|
+
t.is(fastify.pluginName, 'plugin.test -> B')
|
|
476
|
+
})
|
|
477
|
+
next()
|
|
478
|
+
}))
|
|
479
|
+
|
|
480
|
+
fastify.listen(0, err => {
|
|
481
|
+
t.error(err)
|
|
482
|
+
fastify.close()
|
|
483
|
+
})
|
|
484
|
+
})
|
|
485
|
+
|
|
315
486
|
test('plugin incapsulation', t => {
|
|
316
487
|
t.plan(10)
|
|
317
488
|
const fastify = Fastify()
|
package/test/promises.test.js
CHANGED
|
@@ -42,6 +42,24 @@ fastify.get('/double', function (req, reply) {
|
|
|
42
42
|
return Promise.resolve({ hello: '42' })
|
|
43
43
|
})
|
|
44
44
|
|
|
45
|
+
fastify.get('/thenable', opts, function (req, reply) {
|
|
46
|
+
setImmediate(function () {
|
|
47
|
+
reply.send({ hello: 'world' })
|
|
48
|
+
})
|
|
49
|
+
return reply
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
fastify.get('/thenable-error', opts, function (req, reply) {
|
|
53
|
+
setImmediate(function () {
|
|
54
|
+
reply.send(new Error('kaboom'))
|
|
55
|
+
})
|
|
56
|
+
return reply
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
fastify.get('/return-reply', opts, function (req, reply) {
|
|
60
|
+
return reply.send({ hello: 'world' })
|
|
61
|
+
})
|
|
62
|
+
|
|
45
63
|
fastify.listen(0, err => {
|
|
46
64
|
t.error(err)
|
|
47
65
|
fastify.server.unref()
|
|
@@ -82,4 +100,41 @@ fastify.listen(0, err => {
|
|
|
82
100
|
t.deepEqual(JSON.parse(body), { hello: '42' })
|
|
83
101
|
})
|
|
84
102
|
})
|
|
103
|
+
|
|
104
|
+
test('thenable', t => {
|
|
105
|
+
t.plan(4)
|
|
106
|
+
sget({
|
|
107
|
+
method: 'GET',
|
|
108
|
+
url: 'http://localhost:' + fastify.server.address().port + '/thenable'
|
|
109
|
+
}, (err, response, body) => {
|
|
110
|
+
t.error(err)
|
|
111
|
+
t.strictEqual(response.statusCode, 200)
|
|
112
|
+
t.strictEqual(response.headers['content-length'], '' + body.length)
|
|
113
|
+
t.deepEqual(JSON.parse(body), { hello: 'world' })
|
|
114
|
+
})
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
test('thenable (error)', t => {
|
|
118
|
+
t.plan(2)
|
|
119
|
+
sget({
|
|
120
|
+
method: 'GET',
|
|
121
|
+
url: 'http://localhost:' + fastify.server.address().port + '/thenable-error'
|
|
122
|
+
}, (err, response, body) => {
|
|
123
|
+
t.error(err)
|
|
124
|
+
t.strictEqual(response.statusCode, 500)
|
|
125
|
+
})
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
test('return-reply', t => {
|
|
129
|
+
t.plan(4)
|
|
130
|
+
sget({
|
|
131
|
+
method: 'GET',
|
|
132
|
+
url: 'http://localhost:' + fastify.server.address().port + '/return-reply'
|
|
133
|
+
}, (err, response, body) => {
|
|
134
|
+
t.error(err)
|
|
135
|
+
t.strictEqual(response.statusCode, 200)
|
|
136
|
+
t.strictEqual(response.headers['content-length'], '' + body.length)
|
|
137
|
+
t.deepEqual(JSON.parse(body), { hello: 'world' })
|
|
138
|
+
})
|
|
139
|
+
})
|
|
85
140
|
})
|
|
@@ -81,3 +81,79 @@ test('proto-poisoning ignore', t => {
|
|
|
81
81
|
})
|
|
82
82
|
})
|
|
83
83
|
})
|
|
84
|
+
|
|
85
|
+
test('constructor-poisoning ignore (default in v2)', t => {
|
|
86
|
+
t.plan(3)
|
|
87
|
+
|
|
88
|
+
const fastify = Fastify()
|
|
89
|
+
t.tearDown(fastify.close.bind(fastify))
|
|
90
|
+
|
|
91
|
+
fastify.post('/', (request, reply) => {
|
|
92
|
+
reply.send('ok')
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
fastify.listen(0, function (err) {
|
|
96
|
+
t.error(err)
|
|
97
|
+
|
|
98
|
+
sget({
|
|
99
|
+
method: 'POST',
|
|
100
|
+
url: 'http://localhost:' + fastify.server.address().port,
|
|
101
|
+
headers: { 'Content-Type': 'application/json' },
|
|
102
|
+
body: '{ "constructor": { "prototype": { "foo": "bar" } } }'
|
|
103
|
+
}, (err, response, body) => {
|
|
104
|
+
t.error(err)
|
|
105
|
+
t.strictEqual(response.statusCode, 200)
|
|
106
|
+
})
|
|
107
|
+
})
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
test('constructor-poisoning error', t => {
|
|
111
|
+
t.plan(3)
|
|
112
|
+
|
|
113
|
+
const fastify = Fastify({ onConstructorPoisoning: 'error' })
|
|
114
|
+
t.tearDown(fastify.close.bind(fastify))
|
|
115
|
+
|
|
116
|
+
fastify.post('/', (request, reply) => {
|
|
117
|
+
t.fail('handler should not be called')
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
fastify.listen(0, function (err) {
|
|
121
|
+
t.error(err)
|
|
122
|
+
|
|
123
|
+
sget({
|
|
124
|
+
method: 'POST',
|
|
125
|
+
url: 'http://localhost:' + fastify.server.address().port,
|
|
126
|
+
headers: { 'Content-Type': 'application/json' },
|
|
127
|
+
body: '{ "constructor": { "prototype": { "foo": "bar" } } }'
|
|
128
|
+
}, (err, response, body) => {
|
|
129
|
+
t.error(err)
|
|
130
|
+
t.strictEqual(response.statusCode, 400)
|
|
131
|
+
})
|
|
132
|
+
})
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
test('constructor-poisoning remove', t => {
|
|
136
|
+
t.plan(4)
|
|
137
|
+
|
|
138
|
+
const fastify = Fastify({ onProtoPoisoning: 'remove' })
|
|
139
|
+
t.tearDown(fastify.close.bind(fastify))
|
|
140
|
+
|
|
141
|
+
fastify.post('/', (request, reply) => {
|
|
142
|
+
t.equal(undefined, Object.assign({}, request.body).foo)
|
|
143
|
+
reply.send({ ok: true })
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
fastify.listen(0, function (err) {
|
|
147
|
+
t.error(err)
|
|
148
|
+
|
|
149
|
+
sget({
|
|
150
|
+
method: 'POST',
|
|
151
|
+
url: 'http://localhost:' + fastify.server.address().port,
|
|
152
|
+
headers: { 'Content-Type': 'application/json' },
|
|
153
|
+
body: '{ "constructor": { "prototype": { "foo": "bar" } } }'
|
|
154
|
+
}, (err, response, body) => {
|
|
155
|
+
t.error(err)
|
|
156
|
+
t.strictEqual(response.statusCode, 200)
|
|
157
|
+
})
|
|
158
|
+
})
|
|
159
|
+
})
|