@@ -3,207 +3,67 @@ import * as assert from 'assert';
33import * as http from 'http' ;
44import * as net from 'net' ;
55
6- async function createServer ( { expectedBodyLength } ) {
7- const server = http . createServer ( ) ;
8-
9- server . on ( 'request' , common . mustNotCall ( ) ) ;
10-
11- server . on ( 'upgrade' , function ( req , socket , upgradeHead ) {
12- // Confirm the upgrade:
13- socket . write ( 'HTTP/1.1 101 Switching Protocols\r\n' +
14- 'Upgrade: custom-protocol\r\n' +
15- 'Connection: Upgrade\r\n' +
16- '\r\n' ) ;
17-
18- // Read and validate the request body, if and only if expectedBodyLength is set:
19- if ( expectedBodyLength !== undefined ) {
20- let reqBody = '' ;
21- req . on ( 'data' , ( str ) => { reqBody += str ; } ) ;
22- req . on ( 'end' , common . mustCall ( ( ) => {
23- assert . strictEqual ( reqBody . length , expectedBodyLength ) ;
6+ const EXPECTED_BODY_LENGTH = 12 ;
7+
8+ const server = http . createServer ( ) ;
9+ server . on ( 'request' , common . mustNotCall ( ) ) ;
10+ server . on ( 'upgrade' , function ( req , socket , upgradeHead ) {
11+ // Confirm the upgrade:
12+ socket . write ( 'HTTP/1.1 101 Switching Protocols\r\n' +
13+ 'Upgrade: custom-protocol\r\n' +
14+ 'Connection: Upgrade\r\n' +
15+ '\r\n' ) ;
16+
17+ // Read and validate the request body:
18+ let reqBodyLength = 0 ;
19+ req . on ( 'data' , ( chunk ) => { reqBodyLength += chunk . length ; } ) ;
20+ req . on ( 'end' , common . mustCall ( ( ) => {
21+ assert . strictEqual ( reqBodyLength , EXPECTED_BODY_LENGTH ) ;
22+
23+ // Defer upgrade stream read slightly to make sure it doesn't start
24+ // streaming along with the request body, until we actually read it:
25+ setTimeout ( common . mustCall ( ( ) => {
26+ let socketData = upgradeHead ;
27+
28+ socket . on ( 'data' , common . mustCall ( ( d ) => {
29+ socketData = Buffer . concat ( [ socketData , d ] ) ;
2430 } ) ) ;
25- }
26-
27- let socketData = upgradeHead ;
28-
29- // Collect the raw protocol data and check it:
30- socket . on ( 'data' , common . mustCall ( ( d ) => {
31- socketData = Buffer . concat ( [ socketData , d ] ) ;
32- } ) ) ;
33-
34- socket . on ( 'end' , common . mustCall ( ( ) => {
35- assert . strictEqual ( socketData . toString ( ) , 'upgrade head\npost-upgrade message' ) ;
36- socket . end ( ) ;
37- } ) ) ;
38- } ) ;
39-
40- await new Promise ( ( resolve ) => server . listen ( 0 , ( ) => resolve ( ) ) ) ;
41-
42- return server ;
43- }
44-
45- async function testUpgradeWithBody ( ) {
46- const server = await createServer ( { expectedBodyLength : 12 } ) ;
47-
48- const conn = net . createConnection ( server . address ( ) . port ) ;
49- conn . setEncoding ( 'utf8' ) ;
50-
51- await new Promise ( ( resolve ) => conn . on ( 'connect' , resolve ) ) ;
52-
53- // Write request headers, body & upgrade head all together:
54- conn . write (
55- 'POST / HTTP/1.1\r\n' +
56- 'host: localhost\r\n' +
57- 'Upgrade: custom-protocol\r\n' +
58- 'Connection: Upgrade\r\n' +
59- 'transfer-encoding: chunked\r\n' +
60- '\r\n' +
61- 'C\r\nrequest body\r\n' + // 12 byte body sent immediately
62- '0\r\n\r\n' +
63- 'upgrade head'
64- ) ;
65-
66- const response = await new Promise ( ( resolve ) => conn . once ( 'data' , resolve ) ) ;
67- assert . ok ( response . startsWith ( 'HTTP/1.1 101 Switching Protocols\r\n' ) ) ;
68-
69- // Send more data after connection is confirmed:
70- conn . write ( '\npost-upgrade message' ) ;
71- conn . end ( ) ;
72-
73- await new Promise ( ( resolve ) => conn . on ( 'end' , resolve ) ) ;
74-
75- server . close ( ) ;
76- }
77-
78- async function testUpgradeWithLargeBody ( ) {
79- const server = await createServer ( { expectedBodyLength : 100_000 } ) ;
80-
81- const conn = net . createConnection ( server . address ( ) . port ) ;
82- conn . setEncoding ( 'utf8' ) ;
83-
84- await new Promise ( ( resolve ) => conn . on ( 'connect' , resolve ) ) ;
85-
86- // Write request headers, leave the body pending:
87- conn . write (
88- 'POST / HTTP/1.1\r\n' +
89- 'host: localhost\r\n' +
90- 'Upgrade: custom-protocol\r\n' +
91- 'Connection: Upgrade\r\n' +
92- 'transfer-encoding: chunked\r\n' +
93- '\r\n'
94- ) ;
95-
96- await new Promise ( ( resolve ) => setTimeout ( resolve , 10 ) ) ;
9731
98- // Write the large body and part of the initial upgrade data.
99- for ( let i = 0 ; i < 20_000 ; i ++ ) {
100- conn . write ( '5\r\nhello\r\n' ) ; // 10 byte chunk = 5 byte body
101- }
102-
103- // End body and then send upgrade head
104- await new Promise ( ( resolve ) => setTimeout ( resolve , 10 ) ) ;
105-
106- conn . write (
107- '0\r\n\r\n' +
108- 'upgrade head'
109- ) ;
110-
111- const response = await new Promise ( ( resolve ) => conn . once ( 'data' , resolve ) ) ;
112- assert . ok ( response . startsWith ( 'HTTP/1.1 101 Switching Protocols\r\n' ) ) ;
113-
114- // Send more data after connection is confirmed:
115- conn . write ( '\npost-upgrade message' ) ;
116- conn . end ( ) ;
117-
118- await new Promise ( ( resolve ) => conn . on ( 'end' , resolve ) ) ;
119-
120- server . close ( ) ;
121- }
122-
123- async function testUpgradeWithUnreadBody ( ) {
124- const server = await createServer ( {
125- expectedBodyLength : undefined // Don't read the request body at all
126- } ) ;
127-
128- const conn = net . createConnection ( server . address ( ) . port ) ;
129- conn . setEncoding ( 'utf8' ) ;
130-
131- await new Promise ( ( resolve ) => conn . on ( 'connect' , resolve ) ) ;
132-
133- // Write request headers, body & upgrade head all together:
134- conn . write (
135- 'POST / HTTP/1.1\r\n' +
136- 'host: localhost\r\n' +
137- 'Upgrade: custom-protocol\r\n' +
138- 'Connection: Upgrade\r\n' +
139- 'transfer-encoding: chunked\r\n' +
140- '\r\n' +
141- 'C\r\nrequest body\r\n' + // 12 byte body sent immediately
142- '0\r\n\r\n' +
143- 'upgrade head'
144- ) ;
145-
146- const response = await new Promise ( ( resolve ) => conn . once ( 'data' , resolve ) ) ;
147- assert . ok ( response . startsWith ( 'HTTP/1.1 101 Switching Protocols\r\n' ) ) ;
148-
149- // Send more data after connection is confirmed:
150- conn . write ( '\npost-upgrade message' ) ;
151- conn . end ( ) ;
152-
153- await new Promise ( ( resolve ) => conn . on ( 'end' , resolve ) ) ;
154-
155- server . close ( ) ;
156- }
157-
158- async function testUpgradeWithUnreadLargeBody ( ) {
159- const server = await createServer ( {
160- expectedBodyLength : undefined // Don't read the request body at all
161- } ) ;
162-
163- const conn = net . createConnection ( server . address ( ) . port ) ;
164- conn . setEncoding ( 'utf8' ) ;
165-
166- await new Promise ( ( resolve ) => conn . on ( 'connect' , resolve ) ) ;
167-
168- // Write request headers, leave the body pending:
169- conn . write (
170- 'POST / HTTP/1.1\r\n' +
171- 'host: localhost\r\n' +
172- 'Upgrade: custom-protocol\r\n' +
173- 'Connection: Upgrade\r\n' +
174- 'transfer-encoding: chunked\r\n' +
175- '\r\n'
176- ) ;
177-
178- await new Promise ( ( resolve ) => setTimeout ( resolve , 10 ) ) ;
179-
180- // Write the large body and part of the initial upgrade data.
181- for ( let i = 0 ; i < 20_000 ; i ++ ) {
182- conn . write ( '5\r\nhello\r\n' ) ; // 10 byte chunk = 5 byte body
183- }
32+ socket . on ( 'end' , common . mustCall ( ( ) => {
33+ assert . strictEqual ( socketData . toString ( ) , 'upgrade head\npost-upgrade message' ) ;
34+ socket . end ( ) ;
35+ } ) ) ;
36+ } ) , 10 ) ;
37+ } ) ) ;
38+ } ) ;
18439
185- // End body and then send upgrade head
186- await new Promise ( ( resolve ) => setTimeout ( resolve , 10 ) ) ;
40+ await new Promise ( ( resolve ) => server . listen ( 0 , ( ) => resolve ( ) ) ) ;
18741
188- conn . write (
189- '0\r\n\r\n' +
190- 'upgrade head'
191- ) ;
42+ const conn = net . createConnection ( server . address ( ) . port ) ;
43+ conn . setEncoding ( 'utf8' ) ;
19244
193- const response = await new Promise ( ( resolve ) => conn . once ( 'data' , resolve ) ) ;
194- assert . ok ( response . startsWith ( 'HTTP/1.1 101 Switching Protocols\r\n' ) ) ;
45+ await new Promise ( ( resolve ) => conn . on ( 'connect' , resolve ) ) ;
19546
196- // Send more data after connection is confirmed:
197- conn . write ( '\npost-upgrade message' ) ;
198- conn . end ( ) ;
47+ // Write request headers, body & upgrade head all together:
48+ conn . write (
49+ 'POST / HTTP/1.1\r\n' +
50+ 'host: localhost\r\n' +
51+ 'Upgrade: custom-protocol\r\n' +
52+ 'Connection: Upgrade\r\n' +
53+ 'transfer-encoding: chunked\r\n' +
54+ '\r\n' +
55+ 'C\r\nrequest body\r\n' + // 12 byte body sent immediately
56+ '0\r\n\r\n' +
57+ 'upgrade head'
58+ ) ;
19959
200- await new Promise ( ( resolve ) => conn . on ( 'end' , resolve ) ) ;
60+ const response = await new Promise ( ( resolve ) => conn . once ( 'data' , resolve ) ) ;
61+ assert . ok ( response . startsWith ( 'HTTP/1.1 101 Switching Protocols\r\n' ) ) ;
20162
202- server . close ( ) ;
63+ // Send more data after connection is confirmed:
64+ conn . write ( '\npost-upgrade message' ) ;
65+ conn . end ( ) ;
20366
204- }
67+ await new Promise ( ( resolve ) => conn . on ( 'end' , resolve ) ) ;
20568
206- await testUpgradeWithBody ( ) ;
207- await testUpgradeWithLargeBody ( ) ;
208- await testUpgradeWithUnreadBody ( ) ;
209- await testUpgradeWithUnreadLargeBody ( ) ;
69+ server . close ( ) ;
0 commit comments