fastify 3.9.2 → 3.12.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.
Files changed (92) hide show
  1. package/GOVERNANCE.md +1 -1
  2. package/README.md +12 -8
  3. package/SECURITY.md +3 -3
  4. package/docs/ContentTypeParser.md +1 -1
  5. package/docs/Ecosystem.md +16 -6
  6. package/docs/Encapsulation.md +5 -2
  7. package/docs/Fluent-Schema.md +4 -4
  8. package/docs/Getting-Started.md +1 -1
  9. package/docs/Hooks.md +28 -1
  10. package/docs/Lifecycle.md +8 -1
  11. package/docs/Middleware.md +5 -4
  12. package/docs/Reply.md +13 -4
  13. package/docs/Routes.md +4 -3
  14. package/docs/Server.md +78 -4
  15. package/docs/Serverless.md +23 -51
  16. package/docs/TypeScript.md +35 -18
  17. package/docs/Validation-and-Serialization.md +4 -4
  18. package/docs/Write-Plugin.md +4 -4
  19. package/examples/hooks-benchmark.js +12 -12
  20. package/examples/hooks.js +16 -16
  21. package/examples/plugin.js +2 -2
  22. package/examples/route-prefix.js +4 -4
  23. package/fastify.d.ts +16 -1
  24. package/fastify.js +33 -16
  25. package/isolate-0x426d1e0-1227-v8.log +4019 -0
  26. package/isolate-0x4d4c7e0-1988-v8.log +4081 -0
  27. package/lib/errors.js +6 -0
  28. package/lib/headRoute.js +31 -0
  29. package/lib/pluginOverride.js +5 -5
  30. package/lib/pluginUtils.js +7 -6
  31. package/lib/reply.js +14 -2
  32. package/lib/reqIdGenFactory.js +5 -0
  33. package/lib/request.js +1 -1
  34. package/lib/route.js +66 -41
  35. package/lib/schema-compilers.js +5 -3
  36. package/lib/schema-controller.js +106 -0
  37. package/lib/schemas.js +14 -24
  38. package/lib/server.js +1 -0
  39. package/lib/symbols.js +1 -3
  40. package/lib/warnings.js +2 -0
  41. package/lib/wrapThenable.js +2 -1
  42. package/package.json +25 -21
  43. package/test/404s.test.js +120 -120
  44. package/test/500s.test.js +8 -8
  45. package/test/async-await.test.js +29 -1
  46. package/test/close.test.js +8 -8
  47. package/test/context-config.test.js +52 -0
  48. package/test/custom-parser.test.js +8 -8
  49. package/test/decorator.test.js +49 -49
  50. package/test/default-route.test.js +43 -0
  51. package/test/fastify-instance.test.js +2 -2
  52. package/test/fluent-schema.test.js +3 -3
  53. package/test/handler-context.test.js +2 -2
  54. package/test/hooks-async.test.js +3 -3
  55. package/test/hooks.on-ready.test.js +12 -12
  56. package/test/hooks.test.js +75 -32
  57. package/test/http2/closing.test.js +23 -1
  58. package/test/inject.test.js +6 -6
  59. package/test/input-validation.js +2 -2
  60. package/test/internals/hookRunner.test.js +50 -50
  61. package/test/internals/reply.test.js +47 -22
  62. package/test/internals/request.test.js +3 -9
  63. package/test/internals/version.test.js +2 -2
  64. package/test/logger.test.js +30 -30
  65. package/test/middleware.test.js +4 -4
  66. package/test/plugin.helper.js +2 -2
  67. package/test/plugin.test.js +154 -99
  68. package/test/register.test.js +11 -11
  69. package/test/request-error.test.js +2 -2
  70. package/test/route-hooks.test.js +24 -24
  71. package/test/route-prefix.test.js +81 -52
  72. package/test/route.test.js +568 -0
  73. package/test/schema-feature.test.js +168 -38
  74. package/test/schema-serialization.test.js +4 -4
  75. package/test/schema-special-usage.test.js +136 -0
  76. package/test/schema-validation.test.js +7 -7
  77. package/test/skip-reply-send.test.js +315 -0
  78. package/test/stream.test.js +6 -6
  79. package/test/throw.test.js +4 -4
  80. package/test/types/instance.test-d.ts +5 -3
  81. package/test/types/plugin.test-d.ts +7 -7
  82. package/test/types/reply.test-d.ts +1 -0
  83. package/test/types/schema.test-d.ts +15 -0
  84. package/test/validation-error-handling.test.js +5 -5
  85. package/test/versioned-routes.test.js +1 -1
  86. package/types/content-type-parser.d.ts +1 -1
  87. package/types/instance.d.ts +6 -3
  88. package/types/plugin.d.ts +1 -1
  89. package/types/reply.d.ts +1 -0
  90. package/types/route.d.ts +8 -2
  91. package/types/schema.d.ts +3 -0
  92. package/test/skip-reply-send.js +0 -98
@@ -1,10 +1,13 @@
1
1
  'use strict'
2
2
 
3
+ const stream = require('stream')
4
+ const split = require('split2')
3
5
  const t = require('tap')
4
6
  const test = t.test
5
7
  const sget = require('simple-get').concat
6
8
  const joi = require('@hapi/joi')
7
9
  const Fastify = require('..')
10
+ const proxyquire = require('proxyquire')
8
11
 
9
12
  test('route', t => {
10
13
  t.plan(9)
@@ -545,3 +548,568 @@ test('throws when route-level error handler is not a function', t => {
545
548
  t.is(err.message, 'Error Handler for GET:/tea route, if defined, must be a function')
546
549
  }
547
550
  })
551
+
552
+ test('Creates a HEAD route for each GET one', t => {
553
+ t.plan(8)
554
+
555
+ const fastify = Fastify({ exposeHeadRoutes: true })
556
+
557
+ fastify.route({
558
+ method: 'GET',
559
+ path: '/more-coffee',
560
+ handler: (req, reply) => {
561
+ reply.send({ here: 'is coffee' })
562
+ }
563
+ })
564
+
565
+ fastify.route({
566
+ method: 'GET',
567
+ path: '/some-light',
568
+ handler: (req, reply) => {
569
+ reply.send('Get some light!')
570
+ }
571
+ })
572
+
573
+ fastify.inject({
574
+ method: 'HEAD',
575
+ url: '/more-coffee'
576
+ }, (error, res) => {
577
+ t.error(error)
578
+ t.strictEqual(res.statusCode, 200)
579
+ t.strictEqual(res.headers['content-type'], 'application/json; charset=utf-8')
580
+ t.deepEqual(res.body, '')
581
+ })
582
+
583
+ fastify.inject({
584
+ method: 'HEAD',
585
+ url: '/some-light'
586
+ }, (error, res) => {
587
+ t.error(error)
588
+ t.strictEqual(res.statusCode, 200)
589
+ t.strictEqual(res.headers['content-type'], 'text/plain; charset=utf-8')
590
+ t.strictEqual(res.body, '')
591
+ })
592
+ })
593
+
594
+ test('Creates a HEAD route for a GET one with prefixTrailingSlash', async (t) => {
595
+ t.plan(1)
596
+
597
+ const fastify = Fastify()
598
+
599
+ const arr = []
600
+ fastify.register((instance, opts, next) => {
601
+ instance.addHook('onRoute', (routeOptions) => {
602
+ arr.push(`${routeOptions.method} ${routeOptions.url}`)
603
+ })
604
+
605
+ instance.route({
606
+ method: 'GET',
607
+ path: '/',
608
+ exposeHeadRoute: true,
609
+ prefixTrailingSlash: 'both',
610
+ handler: (req, reply) => {
611
+ reply.send({ here: 'is coffee' })
612
+ }
613
+ })
614
+
615
+ next()
616
+ }, { prefix: '/v1' })
617
+
618
+ await fastify.ready()
619
+
620
+ console.log(arr)
621
+ t.ok(true)
622
+ })
623
+
624
+ test('Will not create a HEAD route that is not GET', t => {
625
+ t.plan(11)
626
+
627
+ const fastify = Fastify({ exposeHeadRoutes: true })
628
+
629
+ fastify.route({
630
+ method: 'GET',
631
+ path: '/more-coffee',
632
+ handler: (req, reply) => {
633
+ reply.send({ here: 'is coffee' })
634
+ }
635
+ })
636
+
637
+ fastify.route({
638
+ method: 'GET',
639
+ path: '/some-light',
640
+ handler: (req, reply) => {
641
+ reply.send()
642
+ }
643
+ })
644
+
645
+ fastify.route({
646
+ method: 'POST',
647
+ path: '/something',
648
+ handler: (req, reply) => {
649
+ reply.send({ look: 'It is something!' })
650
+ }
651
+ })
652
+
653
+ fastify.inject({
654
+ method: 'HEAD',
655
+ url: '/more-coffee'
656
+ }, (error, res) => {
657
+ t.error(error)
658
+ t.strictEqual(res.statusCode, 200)
659
+ t.strictEqual(res.headers['content-type'], 'application/json; charset=utf-8')
660
+ t.deepEqual(res.body, '')
661
+ })
662
+
663
+ fastify.inject({
664
+ method: 'HEAD',
665
+ url: '/some-light'
666
+ }, (error, res) => {
667
+ t.error(error)
668
+ t.strictEqual(res.statusCode, 200)
669
+ t.strictEqual(res.headers['content-type'], undefined)
670
+ t.strictEqual(res.headers['content-length'], '0')
671
+ t.strictEqual(res.body, '')
672
+ })
673
+
674
+ fastify.inject({
675
+ method: 'HEAD',
676
+ url: '/something'
677
+ }, (error, res) => {
678
+ t.error(error)
679
+ t.strictEqual(res.statusCode, 404)
680
+ })
681
+ })
682
+
683
+ test('HEAD route should handle properly each response type', t => {
684
+ t.plan(25)
685
+
686
+ const fastify = Fastify({ exposeHeadRoutes: true })
687
+ const resString = 'Found me!'
688
+ const resJSON = { here: 'is Johnny' }
689
+ const resBuffer = Buffer.from('I am a buffer!')
690
+ const resStream = stream.Readable.from('I am a stream!')
691
+
692
+ fastify.route({
693
+ method: 'GET',
694
+ path: '/json',
695
+ handler: (req, reply) => {
696
+ reply.send(resJSON)
697
+ }
698
+ })
699
+
700
+ fastify.route({
701
+ method: 'GET',
702
+ path: '/string',
703
+ handler: (req, reply) => {
704
+ reply.send(resString)
705
+ }
706
+ })
707
+
708
+ fastify.route({
709
+ method: 'GET',
710
+ path: '/buffer',
711
+ handler: (req, reply) => {
712
+ reply.send(resBuffer)
713
+ }
714
+ })
715
+
716
+ fastify.route({
717
+ method: 'GET',
718
+ path: '/buffer-with-content-type',
719
+ handler: (req, reply) => {
720
+ reply.headers({ 'content-type': 'image/jpeg' })
721
+ reply.send(resBuffer)
722
+ }
723
+ })
724
+
725
+ fastify.route({
726
+ method: 'GET',
727
+ path: '/stream',
728
+ handler: (req, reply) => {
729
+ return resStream
730
+ }
731
+ })
732
+
733
+ fastify.inject({
734
+ method: 'HEAD',
735
+ url: '/json'
736
+ }, (error, res) => {
737
+ t.error(error)
738
+ t.strictEqual(res.statusCode, 200)
739
+ t.strictEqual(res.headers['content-type'], 'application/json; charset=utf-8')
740
+ t.strictEqual(res.headers['content-length'], `${Buffer.byteLength(JSON.stringify(resJSON))}`)
741
+ t.deepEqual(res.body, '')
742
+ })
743
+
744
+ fastify.inject({
745
+ method: 'HEAD',
746
+ url: '/string'
747
+ }, (error, res) => {
748
+ t.error(error)
749
+ t.strictEqual(res.statusCode, 200)
750
+ t.strictEqual(res.headers['content-type'], 'text/plain; charset=utf-8')
751
+ t.strictEqual(res.headers['content-length'], `${Buffer.byteLength(resString)}`)
752
+ t.strictEqual(res.body, '')
753
+ })
754
+
755
+ fastify.inject({
756
+ method: 'HEAD',
757
+ url: '/buffer'
758
+ }, (error, res) => {
759
+ t.error(error)
760
+ t.strictEqual(res.statusCode, 200)
761
+ t.strictEqual(res.headers['content-type'], 'application/octet-stream')
762
+ t.strictEqual(res.headers['content-length'], `${resBuffer.byteLength}`)
763
+ t.strictEqual(res.body, '')
764
+ })
765
+
766
+ fastify.inject({
767
+ method: 'HEAD',
768
+ url: '/buffer-with-content-type'
769
+ }, (error, res) => {
770
+ t.error(error)
771
+ t.strictEqual(res.statusCode, 200)
772
+ t.strictEqual(res.headers['content-type'], 'image/jpeg')
773
+ t.strictEqual(res.headers['content-length'], `${resBuffer.byteLength}`)
774
+ t.strictEqual(res.body, '')
775
+ })
776
+
777
+ fastify.inject({
778
+ method: 'HEAD',
779
+ url: '/stream'
780
+ }, (error, res) => {
781
+ t.error(error)
782
+ t.strictEqual(res.statusCode, 200)
783
+ t.strictEqual(res.headers['content-type'], 'application/octet-stream')
784
+ t.strictEqual(res.headers['content-length'], undefined)
785
+ t.strictEqual(res.body, '')
786
+ })
787
+ })
788
+
789
+ test('HEAD route should respect custom onSend handlers', t => {
790
+ t.plan(6)
791
+
792
+ let counter = 0
793
+ const resBuffer = Buffer.from('I am a coffee!')
794
+ const fastify = Fastify({ exposeHeadRoutes: true })
795
+ const customOnSend = (res, reply, payload, done) => {
796
+ counter = counter + 1
797
+ done(null, payload)
798
+ }
799
+
800
+ fastify.route({
801
+ method: 'GET',
802
+ path: '/more-coffee',
803
+ handler: (req, reply) => {
804
+ reply.send(resBuffer)
805
+ },
806
+ onSend: [customOnSend, customOnSend]
807
+ })
808
+
809
+ fastify.inject({
810
+ method: 'HEAD',
811
+ url: '/more-coffee'
812
+ }, (error, res) => {
813
+ t.error(error)
814
+ t.strictEqual(res.statusCode, 200)
815
+ t.strictEqual(res.headers['content-type'], 'application/octet-stream')
816
+ t.strictEqual(res.headers['content-length'], `${resBuffer.byteLength}`)
817
+ t.strictEqual(res.body, '')
818
+ t.strictEqual(counter, 2)
819
+ })
820
+ })
821
+
822
+ test('no warning for exposeHeadRoute', async t => {
823
+ const fastify = Fastify()
824
+
825
+ fastify.route({
826
+ method: 'GET',
827
+ path: '/more-coffee',
828
+ exposeHeadRoute: true,
829
+ async handler () {
830
+ return 'hello world'
831
+ }
832
+ })
833
+
834
+ const listener = (w) => {
835
+ console.error(w)
836
+ t.fail('no warning')
837
+ }
838
+
839
+ process.on('warning', listener)
840
+
841
+ await fastify.listen(0)
842
+
843
+ process.removeListener('warning', listener)
844
+
845
+ await fastify.close()
846
+ })
847
+
848
+ test("HEAD route should handle stream.on('error')", t => {
849
+ t.plan(6)
850
+
851
+ const resStream = stream.Readable.from('Hello with error!')
852
+ const logStream = split(JSON.parse)
853
+ const expectedError = new Error('Hello!')
854
+ const fastify = Fastify({
855
+ logger: {
856
+ stream: logStream,
857
+ level: 'error'
858
+ }
859
+ })
860
+
861
+ fastify.route({
862
+ method: 'GET',
863
+ path: '/more-coffee',
864
+ exposeHeadRoute: true,
865
+ handler: (req, reply) => {
866
+ process.nextTick(() => resStream.emit('error', expectedError))
867
+ return resStream
868
+ }
869
+ })
870
+
871
+ logStream.once('data', line => {
872
+ const { message, stack } = expectedError
873
+ t.deepEquals(line.err, { type: 'Error', message, stack })
874
+ t.equal(line.msg, 'Error on Stream found for HEAD route')
875
+ t.equal(line.level, 50)
876
+ })
877
+
878
+ fastify.inject({
879
+ method: 'HEAD',
880
+ url: '/more-coffee'
881
+ }, (error, res) => {
882
+ t.error(error)
883
+ t.strictEqual(res.statusCode, 200)
884
+ t.strictEqual(res.headers['content-type'], 'application/octet-stream')
885
+ })
886
+ })
887
+
888
+ test('HEAD route should not be exposed by default', t => {
889
+ t.plan(7)
890
+
891
+ const resStream = stream.Readable.from('Hello with error!')
892
+ const resJson = { hello: 'world' }
893
+ const fastify = Fastify()
894
+
895
+ fastify.route({
896
+ method: 'GET',
897
+ path: '/without-flag',
898
+ handler: (req, reply) => {
899
+ return resStream
900
+ }
901
+ })
902
+
903
+ fastify.route({
904
+ exposeHeadRoute: true,
905
+ method: 'GET',
906
+ path: '/with-flag',
907
+ handler: (req, reply) => {
908
+ return resJson
909
+ }
910
+ })
911
+
912
+ fastify.inject({
913
+ method: 'HEAD',
914
+ url: '/without-flag'
915
+ }, (error, res) => {
916
+ t.error(error)
917
+ t.strictEqual(res.statusCode, 404)
918
+ })
919
+
920
+ fastify.inject({
921
+ method: 'HEAD',
922
+ url: '/with-flag'
923
+ }, (error, res) => {
924
+ t.error(error)
925
+ t.strictEqual(res.statusCode, 200)
926
+ t.strictEqual(res.headers['content-type'], 'application/json; charset=utf-8')
927
+ t.strictEqual(res.headers['content-length'], `${Buffer.byteLength(JSON.stringify(resJson))}`)
928
+ t.strictEqual(res.body, '')
929
+ })
930
+ })
931
+
932
+ test('HEAD route should be exposed if route exposeHeadRoute is set', t => {
933
+ t.plan(7)
934
+
935
+ const resBuffer = Buffer.from('I am a coffee!')
936
+ const resJson = { hello: 'world' }
937
+ const fastify = Fastify({ exposeHeadRoutes: false })
938
+
939
+ fastify.route({
940
+ exposeHeadRoute: true,
941
+ method: 'GET',
942
+ path: '/one',
943
+ handler: (req, reply) => {
944
+ return resBuffer
945
+ }
946
+ })
947
+
948
+ fastify.route({
949
+ method: 'GET',
950
+ path: '/two',
951
+ handler: (req, reply) => {
952
+ return resJson
953
+ }
954
+ })
955
+
956
+ fastify.inject({
957
+ method: 'HEAD',
958
+ url: '/one'
959
+ }, (error, res) => {
960
+ t.error(error)
961
+ t.strictEqual(res.statusCode, 200)
962
+ t.strictEqual(res.headers['content-type'], 'application/octet-stream')
963
+ t.strictEqual(res.headers['content-length'], `${resBuffer.byteLength}`)
964
+ t.strictEqual(res.body, '')
965
+ })
966
+
967
+ fastify.inject({
968
+ method: 'HEAD',
969
+ url: '/two'
970
+ }, (error, res) => {
971
+ t.error(error)
972
+ t.strictEqual(res.statusCode, 404)
973
+ })
974
+ })
975
+
976
+ test('Set a custom HEAD route before GET one without disabling exposeHeadRoutes (global)', t => {
977
+ t.plan(6)
978
+
979
+ const resBuffer = Buffer.from('I am a coffee!')
980
+ const fastify = Fastify({
981
+ exposeHeadRoutes: true
982
+ })
983
+
984
+ fastify.route({
985
+ method: 'HEAD',
986
+ path: '/one',
987
+ handler: (req, reply) => {
988
+ reply.header('content-type', 'application/pdf')
989
+ reply.header('content-length', `${resBuffer.byteLength}`)
990
+ reply.header('x-custom-header', 'some-custom-header')
991
+ reply.send()
992
+ }
993
+ })
994
+
995
+ fastify.route({
996
+ method: 'GET',
997
+ path: '/one',
998
+ handler: (req, reply) => {
999
+ return resBuffer
1000
+ }
1001
+ })
1002
+
1003
+ fastify.inject({
1004
+ method: 'HEAD',
1005
+ url: '/one'
1006
+ }, (error, res) => {
1007
+ t.error(error)
1008
+ t.strictEqual(res.statusCode, 200)
1009
+ t.strictEqual(res.headers['content-type'], 'application/pdf')
1010
+ t.strictEqual(res.headers['content-length'], `${resBuffer.byteLength}`)
1011
+ t.strictEqual(res.headers['x-custom-header'], 'some-custom-header')
1012
+ t.strictEqual(res.body, '')
1013
+ })
1014
+ })
1015
+
1016
+ test('Set a custom HEAD route before GET one without disabling exposeHeadRoutes (route)', t => {
1017
+ t.plan(7)
1018
+
1019
+ function onWarning (code) {
1020
+ t.strictEqual(code, 'FSTDEP007')
1021
+ }
1022
+ const warning = {
1023
+ emit: onWarning
1024
+ }
1025
+
1026
+ const route = proxyquire('../lib/route', { './warnings': warning })
1027
+ const fastify = proxyquire('..', { './lib/route.js': route })()
1028
+
1029
+ const resBuffer = Buffer.from('I am a coffee!')
1030
+
1031
+ fastify.route({
1032
+ method: 'HEAD',
1033
+ path: '/one',
1034
+ handler: (req, reply) => {
1035
+ reply.header('content-type', 'application/pdf')
1036
+ reply.header('content-length', `${resBuffer.byteLength}`)
1037
+ reply.header('x-custom-header', 'some-custom-header')
1038
+ reply.send()
1039
+ }
1040
+ })
1041
+
1042
+ fastify.route({
1043
+ method: 'GET',
1044
+ exposeHeadRoute: true,
1045
+ path: '/one',
1046
+ handler: (req, reply) => {
1047
+ return resBuffer
1048
+ }
1049
+ })
1050
+
1051
+ fastify.inject({
1052
+ method: 'HEAD',
1053
+ url: '/one'
1054
+ }, (error, res) => {
1055
+ t.error(error)
1056
+ t.strictEqual(res.statusCode, 200)
1057
+ t.strictEqual(res.headers['content-type'], 'application/pdf')
1058
+ t.strictEqual(res.headers['content-length'], `${resBuffer.byteLength}`)
1059
+ t.strictEqual(res.headers['x-custom-header'], 'some-custom-header')
1060
+ t.strictEqual(res.body, '')
1061
+ })
1062
+ })
1063
+
1064
+ test('HEAD routes properly auto created for GET routes when prefixTrailingSlash: \'no-slash\'', t => {
1065
+ t.plan(2)
1066
+
1067
+ const fastify = Fastify()
1068
+
1069
+ fastify.register(function routes (f, opts, next) {
1070
+ f.route({
1071
+ method: 'GET',
1072
+ url: '/',
1073
+ exposeHeadRoute: true,
1074
+ prefixTrailingSlash: 'no-slash',
1075
+ handler: (req, reply) => {
1076
+ reply.send({ hello: 'world' })
1077
+ }
1078
+ })
1079
+
1080
+ next()
1081
+ }, { prefix: '/prefix' })
1082
+
1083
+ fastify.inject({ url: '/prefix/prefix', method: 'HEAD' }, (err, res) => {
1084
+ t.error(err)
1085
+ t.strictEquals(res.statusCode, 404)
1086
+ })
1087
+ })
1088
+
1089
+ test('HEAD routes properly auto created for GET routes when prefixTrailingSlash: \'both\'', async t => {
1090
+ t.plan(3)
1091
+
1092
+ const fastify = Fastify()
1093
+
1094
+ fastify.register(function routes (f, opts, next) {
1095
+ f.route({
1096
+ method: 'GET',
1097
+ url: '/',
1098
+ exposeHeadRoute: true,
1099
+ prefixTrailingSlash: 'both',
1100
+ handler: (req, reply) => {
1101
+ reply.send({ hello: 'world' })
1102
+ }
1103
+ })
1104
+
1105
+ next()
1106
+ }, { prefix: '/prefix' })
1107
+
1108
+ const doublePrefixReply = await fastify.inject({ url: '/prefix/prefix', method: 'HEAD' })
1109
+ const trailingSlashReply = await fastify.inject({ url: '/prefix/', method: 'HEAD' })
1110
+ const noneTrailingReply = await fastify.inject({ url: '/prefix', method: 'HEAD' })
1111
+
1112
+ t.equals(doublePrefixReply.statusCode, 404)
1113
+ t.equals(trailingSlashReply.statusCode, 200)
1114
+ t.equals(noneTrailingReply.statusCode, 200)
1115
+ })