1
1
import * as _ from 'lodash' ;
2
2
import * as WebSocket from 'isomorphic-ws' ;
3
+ import { PassThrough } from 'stream' ;
3
4
4
5
import {
5
6
getLocal ,
@@ -10,7 +11,8 @@ import {
10
11
delay ,
11
12
expect ,
12
13
fetch ,
13
- isNode
14
+ isNode ,
15
+ nodeOnly
14
16
} from "../../test-utils" ;
15
17
16
18
describe ( "Rule event susbcriptions" , ( ) => {
@@ -227,6 +229,80 @@ describe("Rule event susbcriptions", () => {
227
229
expect ( responseBodyEvent . rawBody . toString ( 'utf8' ) ) . to . equal ( 'Original response body' ) ;
228
230
} ) ;
229
231
232
+
233
+ it ( "should fire abort event if upstream body response fails" , async ( ) => {
234
+ await remoteServer . forAnyRequest ( ) . thenCloseConnection ( ) ;
235
+ const forwardingRule = await server . forAnyRequest ( ) . thenForwardTo ( remoteServer . url ) ;
236
+
237
+ const ruleEvents : RuleEvent < any > [ ] = [ ] ;
238
+ await server . on ( 'rule-event' , ( e ) => ruleEvents . push ( e ) ) ;
239
+
240
+ await fetch ( server . url ) . catch ( ( ) => { } ) ;
241
+
242
+ await delay ( 100 ) ;
243
+ expect ( ruleEvents . length ) . to . equal ( 3 ) ;
244
+
245
+ const requestId = ( await forwardingRule . getSeenRequests ( ) ) [ 0 ] . id ;
246
+ ruleEvents . forEach ( ( event ) => {
247
+ expect ( event . ruleId ) . to . equal ( forwardingRule . id ) ;
248
+ expect ( event . requestId ) . to . equal ( requestId ) ;
249
+ } ) ;
250
+
251
+ expect ( ruleEvents . map ( e => e . eventType ) ) . to . deep . equal ( [
252
+ 'passthrough-request-head' ,
253
+ 'passthrough-request-body' ,
254
+ 'passthrough-abort'
255
+ ] ) ;
256
+
257
+ const responseAbortEvent = ruleEvents [ 2 ] . eventData ;
258
+ expect ( responseAbortEvent . error . name ) . to . equal ( 'Error' ) ;
259
+ expect ( responseAbortEvent . error . message ) . to . equal ( 'socket hang up' ) ;
260
+ } ) ;
261
+
262
+ nodeOnly ( ( ) => {
263
+ it ( "should fire abort event if upstream body response fails" , async ( ) => {
264
+ const stream = new PassThrough ( ) ;
265
+ await remoteServer . forAnyRequest ( ) . thenStream ( 200 , stream ) ;
266
+ const forwardingRule = await server . forAnyRequest ( ) . thenForwardTo ( remoteServer . url , {
267
+ transformResponse : {
268
+ replaceBody : 'replaced body'
269
+ }
270
+ } ) ;
271
+
272
+ const ruleEvents : RuleEvent < any > [ ] = [ ] ;
273
+ await server . on ( 'rule-event' , ( e ) => ruleEvents . push ( e ) ) ;
274
+
275
+ const response = await fetch ( server . url ) ;
276
+ expect ( response . status ) . to . equal ( 200 ) ;
277
+
278
+ stream . emit ( 'error' , new Error ( ) ) ; // Hard-fail part way through the body response
279
+ await delay ( 10 ) ;
280
+
281
+ expect ( ruleEvents . length ) . to . equal ( 4 ) ;
282
+
283
+ const requestId = ( await forwardingRule . getSeenRequests ( ) ) [ 0 ] . id ;
284
+ ruleEvents . forEach ( ( event ) => {
285
+ expect ( event . ruleId ) . to . equal ( forwardingRule . id ) ;
286
+ expect ( event . requestId ) . to . equal ( requestId ) ;
287
+ } ) ;
288
+
289
+ expect ( ruleEvents . map ( e => e . eventType ) ) . to . deep . equal ( [
290
+ 'passthrough-request-head' ,
291
+ 'passthrough-request-body' ,
292
+ 'passthrough-response-head' ,
293
+ 'passthrough-abort'
294
+ ] ) ;
295
+
296
+ const responseHeadEvent = ruleEvents [ 2 ] . eventData ;
297
+ expect ( responseHeadEvent . statusCode ) . to . equal ( 200 ) ; // <-- Original status
298
+
299
+ const responseAbortEvent = ruleEvents [ 3 ] . eventData ;
300
+ expect ( responseAbortEvent . error . name ) . to . equal ( 'Error' ) ;
301
+ expect ( responseAbortEvent . error . code ) . to . equal ( 'ECONNRESET' ) ;
302
+ expect ( responseAbortEvent . error . message ) . to . equal ( 'aborted' ) ;
303
+ } ) ;
304
+ } ) ;
305
+
230
306
it ( "should fire for proxied websockets" , async ( ) => {
231
307
await remoteServer . forAnyWebSocket ( ) . thenPassivelyListen ( ) ;
232
308
const forwardingRule = await server . forAnyWebSocket ( ) . thenForwardTo ( remoteServer . url ) ;
0 commit comments