1
+ import * as net from 'net' ;
2
+ import * as http from 'http' ;
3
+ import { expect } from 'chai' ;
4
+ import { DestroyableServer , makeDestroyable } from 'destroyable-server' ;
5
+ import * as streamConsumers from 'stream/consumers' ;
6
+
7
+ import { createServer } from '../src/server.js' ;
8
+ import { delay } from '@httptoolkit/util' ;
9
+
10
+ describe ( "Trailers endpoint" , ( ) => {
11
+
12
+ let server : DestroyableServer ;
13
+ let serverPort : number ;
14
+
15
+ beforeEach ( async ( ) => {
16
+ server = makeDestroyable ( await createServer ( ) ) ;
17
+ await new Promise < void > ( ( resolve ) => server . listen ( resolve ) ) ;
18
+ serverPort = ( server . address ( ) as net . AddressInfo ) . port ;
19
+ } ) ;
20
+
21
+ afterEach ( async ( ) => {
22
+ await server . destroy ( ) ;
23
+ } ) ;
24
+
25
+ it ( "sends no trailers or metadata for a plain request" , async ( ) => {
26
+ const address = `http://localhost:${ serverPort } /trailers` ;
27
+ const response = await fetch ( address ) ;
28
+
29
+ expect ( response . status ) . to . equal ( 200 ) ;
30
+
31
+ const body = await response . json ( ) ;
32
+ expect ( body ) . to . deep . equal ( {
33
+ 'will-send-trailers' : false ,
34
+ 'received-trailers' : [ ]
35
+ } ) ;
36
+ } ) ;
37
+
38
+ it ( "sends no trailers given a plain request" , async ( ) => {
39
+ const address = `http://localhost:${ serverPort } /trailers` ;
40
+ const request = http . request ( address ) . end ( ) ;
41
+
42
+ const response : http . IncomingMessage = await new Promise ( ( resolve , reject ) => {
43
+ request . on ( 'response' , resolve ) ;
44
+ request . on ( 'error' , reject ) ;
45
+ } ) ;
46
+
47
+ const responseData = await streamConsumers . json ( response ) ;
48
+
49
+ expect ( response . statusCode ) . to . equal ( 200 ) ;
50
+ expect ( responseData ) . to . deep . equal ( {
51
+ 'will-send-trailers' : false ,
52
+ 'received-trailers' : [ ]
53
+ } ) ;
54
+
55
+ expect ( response . rawTrailers ) . to . deep . equal ( [ ] ) ;
56
+ } ) ;
57
+
58
+ it ( "sends trailers given TE: trailers" , async ( ) => {
59
+ const address = `http://localhost:${ serverPort } /trailers` ;
60
+ const request = http . request ( address , {
61
+ headers : {
62
+ 'TE' : 'trailers'
63
+ }
64
+ } ) . end ( ) ;
65
+
66
+ const response : http . IncomingMessage = await new Promise ( ( resolve , reject ) => {
67
+ request . on ( 'response' , resolve ) ;
68
+ request . on ( 'error' , reject ) ;
69
+ } ) ;
70
+
71
+ const responseData = await streamConsumers . json ( response ) ;
72
+
73
+ expect ( response . statusCode ) . to . equal ( 200 ) ;
74
+ expect ( responseData ) . to . deep . equal ( {
75
+ 'will-send-trailers' : true ,
76
+ 'received-trailers' : [ ]
77
+ } ) ;
78
+
79
+ expect ( response . rawTrailers ) . to . deep . equal ( [
80
+ 'example-trailer' , 'example value'
81
+ ] ) ;
82
+ } ) ;
83
+
84
+ it ( "logs the received trailers if provided" , async ( ) => {
85
+ const address = `http://localhost:${ serverPort } /trailers` ;
86
+ const request = http . request ( address , {
87
+ method : 'POST'
88
+ } ) ;
89
+
90
+ request . flushHeaders ( ) ;
91
+ await delay ( 50 ) ; // Make sure it handles slow requests
92
+
93
+ request . addTrailers ( [
94
+ [ 'request-TRAILER' , 'Request value' ] ,
95
+ ] ) ;
96
+ request . end ( 'hello' ) ;
97
+
98
+ const response : http . IncomingMessage = await new Promise ( ( resolve , reject ) => {
99
+ request . on ( 'response' , resolve ) ;
100
+ request . on ( 'error' , reject ) ;
101
+ } ) ;
102
+
103
+ const responseData = await streamConsumers . json ( response ) ;
104
+
105
+ expect ( response . statusCode ) . to . equal ( 200 ) ;
106
+ expect ( responseData ) . to . deep . equal ( {
107
+ 'will-send-trailers' : false ,
108
+ 'received-trailers' : [ 'request-TRAILER' , 'Request value' ]
109
+ } ) ;
110
+ } ) ;
111
+
112
+ } ) ;
0 commit comments