Skip to content

Commit 33b0d0a

Browse files
committed
Improve filtering support for non-HTTP traffic
This adds support for filtering on pending/completed/aborted on non-HTTP traffic, adds webrtc & unknown options to protocol= filters, and stops the errorer filter from treating all non-HTTP as errors (oops).
1 parent 7f03a05 commit 33b0d0a

File tree

3 files changed

+61
-23
lines changed

3 files changed

+61
-23
lines changed

src/model/events/event-base.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,18 @@ export abstract class HTKEventBase {
2525
isTlsTunnel(): this is TlsTunnel { return false; }
2626
isRawTunnel(): this is RawTunnel { return false; }
2727

28+
isTunnel(): this is TlsTunnel | RawTunnel {
29+
return this.isTlsTunnel() || this.isRawTunnel();
30+
}
31+
2832
isRTCConnection(): this is RTCConnection { return false; }
2933
isRTCDataChannel(): this is RTCDataChannel { return false; }
3034
isRTCMediaTrack(): this is RTCMediaTrack { return false; }
3135

36+
isRTC(): this is RTCConnection | RTCDataChannel | RTCMediaTrack {
37+
return this.isRTCConnection() || this.isRTCDataChannel() || this.isRTCMediaTrack();
38+
}
39+
3240
@computed
3341
public get category() {
3442
return getEventCategory(this);

src/model/filters/search-filters.ts

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -316,12 +316,14 @@ class CompletedFilter extends Filter {
316316
static filterName = "completed";
317317

318318
static filterDescription(value: string) {
319-
return "requests that have received a response";
319+
return "requests & connections that have completed without errors";
320320
}
321321

322322
matches(event: ViewableEvent): boolean {
323-
return event.isHttp() &&
324-
event.isSuccessfulExchange();
323+
return (event.isHttp() && event.isSuccessfulExchange() && !event.isWebSocket()) ||
324+
(event.isWebSocket() && event.closeState && event.closeState !== 'aborted') ||
325+
(event.isRTC() && !!event.closeState) ||
326+
(event.isTunnel() && !event.isOpen());
325327
}
326328

327329
toString() {
@@ -336,12 +338,14 @@ class PendingFilter extends Filter {
336338
static filterName = "pending";
337339

338340
static filterDescription(value: string) {
339-
return "requests that are still waiting for a response";
341+
return "requests & connections that are still ongoing";
340342
}
341343

342344
matches(event: ViewableEvent): boolean {
343-
return event.isHttp() &&
344-
!event.isCompletedExchange();
345+
return (event.isHttp() && !event.isCompletedExchange()) ||
346+
(event.isWebSocket() && !event.closeState) ||
347+
(event.isRTC() && !event.closeState) ||
348+
(event.isTunnel() && event.isOpen());
345349
}
346350

347351
toString() {
@@ -356,12 +360,13 @@ class AbortedFilter extends Filter {
356360
static filterName = "aborted";
357361

358362
static filterDescription(value: string) {
359-
return "requests whose connection failed before receiving a response";
363+
return "requests & connections which failed to cleanly complete";
360364
}
361365

362366
matches(event: ViewableEvent): boolean {
363-
return event.isHttp() &&
364-
event.response === 'aborted'
367+
return (event.isHttp() && event.response === 'aborted') ||
368+
(event.isWebSocket() && event.closeState === 'aborted') ||
369+
event.isTlsFailure();
365370
}
366371

367372
toString() {
@@ -380,11 +385,11 @@ class ErrorFilter extends Filter {
380385
}
381386

382387
matches(event: ViewableEvent): boolean {
383-
return !(event.isHttp()) || // TLS Error
384-
event.tags.some(tag =>
388+
return event.isTlsFailure() ||
389+
(event.isHttp() && event.tags.some(tag =>
385390
tag.startsWith('client-error') ||
386391
tag.startsWith('passthrough-error')
387-
);
392+
));
388393
}
389394

390395
toString() {
@@ -489,7 +494,7 @@ class MethodFilter extends Filter {
489494

490495
static filterName = "method";
491496

492-
static filterDescription(value: string) {
497+
static filterDescription(value: string): string {
493498
const [, op, method] = tryParseFilter(MethodFilter, value);
494499

495500
if (!op) {
@@ -604,7 +609,9 @@ class ProtocolFilter extends Filter {
604609
"http",
605610
"https",
606611
"ws",
607-
"wss"
612+
"wss",
613+
"webrtc",
614+
"unknown"
608615
])
609616
] as const;
610617

@@ -614,9 +621,16 @@ class ProtocolFilter extends Filter {
614621
const [, , protocol] = tryParseFilter(ProtocolFilter, value);
615622

616623
if (!protocol) {
617-
return "exchanges using HTTP, HTTPS, WS or WSS";
624+
return "traffic using a specific protocol like HTTPS, or WebSockets";
625+
} else if (protocol === 'unknown') {
626+
return "traffic with no identified protocol";
618627
} else {
619-
return `exchanges using ${protocol.toUpperCase()}`;
628+
return `${
629+
protocol === 'webrtc'
630+
? 'WebRTC'
631+
// HTTP et al:
632+
: protocol.toUpperCase()
633+
} traffic`;
620634
}
621635
}
622636

@@ -629,15 +643,30 @@ class ProtocolFilter extends Filter {
629643
}
630644

631645
matches(event: ViewableEvent): boolean {
632-
if (!(event.isHttp())) return false;
646+
if (this.expectedProtocol === 'unknown') {
647+
return !event.isHttp() && !event.isRTC();
648+
}
649+
650+
if (this.expectedProtocol === 'webrtc') {
651+
return event.isRTC();
652+
}
653+
654+
if (!(event.isHttp())) {
655+
return false;
656+
}
633657

634658
// Parsed protocol is like 'http:', so we strip the colon
635659
const protocol = event.request.parsedUrl.protocol.toLowerCase().slice(0, -1);
636660
return protocol === this.expectedProtocol;
637661
}
638662

639663
toString() {
640-
return `${this.expectedProtocol.toUpperCase()}`;
664+
return this.expectedProtocol === 'unknown'
665+
? 'Unknown protocol'
666+
: this.expectedProtocol === 'webrtc'
667+
? 'WebRTC'
668+
// HTTP et al:
669+
: `${this.expectedProtocol.toUpperCase()}`;
641670
}
642671
}
643672

test/unit/model/filters/search-filter-integration.spec.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,14 @@ describe("Search filter model integration test:", () => {
102102
"exchanges by body content",
103103
"exchanges by body size",
104104
"exchanges that contain a given value anywhere",
105-
"requests that have received a response",
106-
"requests that are still waiting for a response",
107-
"requests whose connection failed before receiving a response",
105+
"requests & connections that have completed without errors",
106+
"requests & connections that are still ongoing",
107+
"requests & connections which failed to cleanly complete",
108108
"requests that weren't transmitted successfully",
109109
"exchanges that are pinned",
110110
"exchanges by their general category",
111111
"requests sent to a given port",
112-
"exchanges using HTTP, HTTPS, WS or WSS",
112+
"traffic using a specific protocol like HTTPS, or WebSockets",
113113
"exchanges using a given version of HTTP",
114114
"websocket streams",
115115
"exchanges that do not match a given condition",
@@ -333,8 +333,9 @@ describe("Search filter model integration test:", () => {
333333
];
334334

335335
const matchedEvents = exampleEvents.filter(e => filter.matches(e));
336-
expect(matchedEvents.length).to.equal(1);
336+
expect(matchedEvents.length).to.equal(2);
337337
expect((matchedEvents[0] as HttpExchange).response).to.equal('aborted');
338+
expect(matchedEvents[1].isTlsFailure()).to.equal(true);
338339
});
339340
});
340341

0 commit comments

Comments
 (0)