1
1
import * as _ from 'lodash' ;
2
2
import HttpsProxyAgent = require( 'https-proxy-agent' ) ;
3
- import * as semver from 'semver' ;
4
3
5
4
import {
6
5
getLocal ,
@@ -16,7 +15,6 @@ import {
16
15
delay ,
17
16
openRawSocket ,
18
17
openRawTlsSocket ,
19
- writeAndReset ,
20
18
watchForEvent ,
21
19
http2DirectRequest
22
20
} from "../../test-utils" ;
@@ -149,41 +147,63 @@ describe("TLS error subscriptions", () => {
149
147
await expectNoClientErrors ( ) ;
150
148
} ) ;
151
149
152
- it ( "should not be sent for requests from TLS clients that reset later in the connection" , async function ( ) {
153
- this . retries ( 3 ) ; // Can be slightly unstable, due to the race for RESET
150
+ it ( "should be sent for requests from TLS clients that reset directly after handshake" , async function ( ) {
151
+ const events : any [ ] = [ ] ;
152
+ await goodServer . on ( 'tls-client-error' , ( ) => events . push ( 'tls-client-error' ) ) ;
153
+ await goodServer . on ( 'client-error' , ( ) => events . push ( 'client-error' ) ) ;
154
+
155
+ const tcpSocket = await openRawSocket ( goodServer )
156
+ await openRawTlsSocket ( tcpSocket ) ;
157
+ tcpSocket . resetAndDestroy ( ) ;
158
+
159
+ await delay ( 50 ) ;
154
160
161
+ // We see a TLS error (reset like this is a common form of cert rejection) but no client error
162
+ // (no HTTP request has even been attempted):
163
+ expect ( events ) . to . deep . equal ( [ 'tls-client-error' ] ) ;
164
+ } ) ;
165
+
166
+ it ( "should not be sent for requests from TLS clients that reset later in the connection" , async function ( ) {
155
167
let seenTlsErrorPromise = getDeferred < TlsHandshakeFailure > ( ) ;
156
168
await goodServer . on ( 'tls-client-error' , ( r ) => seenTlsErrorPromise . resolve ( r ) ) ;
157
169
158
170
let seenClientErrorPromise = getDeferred < ClientError > ( ) ;
159
171
await goodServer . on ( 'client-error' , ( e ) => seenClientErrorPromise . resolve ( e ) ) ;
160
172
161
- const tlsSocket = await openRawTlsSocket ( goodServer ) ;
162
- writeAndReset ( tlsSocket , "GET / HTTP/1.1\r\n\r\n" ) ;
173
+ const tcpSocket = await openRawSocket ( goodServer )
174
+ const tlsSocket = await openRawTlsSocket ( tcpSocket ) ;
175
+ tlsSocket . write ( "GET / HTTP/1.1\r\nHost: hello.world.invalid\r\n" ) ; // Incomplete HTTP request
176
+
177
+ // Kill the underlying socket before the request head completes (but after some content is sent):
178
+ setTimeout ( ( ) => {
179
+ tcpSocket . resetAndDestroy ( )
180
+ } , 10 ) ;
163
181
164
182
const seenTlsError = await Promise . race ( [
165
- delay ( 100 ) . then ( ( ) => false ) ,
183
+ delay ( 50 ) . then ( ( ) => false ) ,
166
184
seenTlsErrorPromise
167
185
] ) ;
168
- expect ( seenTlsError ) . to . equal ( false ) ;
186
+
169
187
170
188
// No TLS error, but we do expect a client reset error:
189
+ expect ( seenTlsError ) . to . equal ( false ) ;
171
190
expect ( ( await seenClientErrorPromise ) . errorCode ) . to . equal ( 'ECONNRESET' ) ;
172
191
} ) ;
173
192
174
193
it ( "should not be sent for requests from non-TLS clients that reset before sending anything" , async ( ) => {
175
194
let seenTlsErrorPromise = getDeferred < TlsHandshakeFailure > ( ) ;
176
195
await goodServer . on ( 'tls-client-error' , ( r ) => seenTlsErrorPromise . resolve ( r ) ) ;
177
196
178
- const tlsSocket = await openRawSocket ( goodServer ) ;
179
- writeAndReset ( tlsSocket , "" ) ; // Send nothing, just connect & RESET
197
+ const rawSocket = await openRawSocket ( goodServer ) ;
198
+ rawSocket . resetAndDestroy ( ) ; // Immediate reset without sending any data
180
199
181
200
const seenTlsError = await Promise . race ( [
182
- delay ( 100 ) . then ( ( ) => false ) ,
201
+ delay ( 50 ) . then ( ( ) => false ) ,
183
202
seenTlsErrorPromise
184
203
] ) ;
185
- expect ( seenTlsError ) . to . equal ( false ) ;
186
204
205
+ // No TLS error, no client reset error:
206
+ expect ( seenTlsError ) . to . equal ( false ) ;
187
207
await expectNoClientErrors ( ) ;
188
208
} ) ;
189
209
} ) ;
0 commit comments