web flow filter refactoring
parent
043f32ccb8
commit
858b8d2274
@ -0,0 +1,125 @@
|
|||||||
|
import type { Flow, Header } from './flow'
|
||||||
|
|
||||||
|
const FLOW_FILTER_SCOPES = ['url', 'method', 'code', 'header', 'reqheader', 'resheader', 'body', 'reqbody', 'resbody', 'all'] as const
|
||||||
|
type FlowFilterScope = typeof FLOW_FILTER_SCOPES[number]
|
||||||
|
|
||||||
|
export class FlowFilter {
|
||||||
|
private keyword: string | RegExp | undefined
|
||||||
|
private scope: FlowFilterScope = 'url'
|
||||||
|
|
||||||
|
constructor(text: string) {
|
||||||
|
text = text.trim()
|
||||||
|
if (!text) return
|
||||||
|
|
||||||
|
for (const scope of FLOW_FILTER_SCOPES) {
|
||||||
|
if (text.startsWith(`${scope}:`)) {
|
||||||
|
this.scope = scope
|
||||||
|
text = text.replace(`${scope}:`, '').trim()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!text) return
|
||||||
|
|
||||||
|
// regexp
|
||||||
|
if (text.startsWith('/') && (text.endsWith('/') || text.endsWith('/i'))) {
|
||||||
|
let flags: string | undefined
|
||||||
|
if (text.endsWith('i')) {
|
||||||
|
flags = 'i'
|
||||||
|
text = text.slice(0, -1)
|
||||||
|
}
|
||||||
|
text = text.slice(1, -1).trim()
|
||||||
|
if (!text) return
|
||||||
|
this.keyword = new RegExp(text, flags)
|
||||||
|
}
|
||||||
|
// string
|
||||||
|
else {
|
||||||
|
this.keyword = text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public match(flow: Flow): boolean {
|
||||||
|
switch (this.scope) {
|
||||||
|
case 'url':
|
||||||
|
return this.matchUrl(flow)
|
||||||
|
case 'method':
|
||||||
|
return this.matchMethod(flow)
|
||||||
|
case 'code':
|
||||||
|
return this.matchCode(flow)
|
||||||
|
case 'reqheader':
|
||||||
|
return this.matchReqHeader(flow)
|
||||||
|
case 'resheader':
|
||||||
|
return this.matchResHeader(flow)
|
||||||
|
case 'header':
|
||||||
|
return this.matchHeader(flow)
|
||||||
|
case 'reqbody':
|
||||||
|
return this.matchReqBody(flow)
|
||||||
|
case 'resbody':
|
||||||
|
return this.matchResBody(flow)
|
||||||
|
case 'body':
|
||||||
|
return this.matchBody(flow)
|
||||||
|
case 'all':
|
||||||
|
return this.matchAll(flow)
|
||||||
|
default:
|
||||||
|
throw new Error(`invalid scope ${this.scope}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private matchUrl(flow: Flow): boolean {
|
||||||
|
return this.matchKeyword(flow.request.url)
|
||||||
|
}
|
||||||
|
|
||||||
|
private matchMethod(flow: Flow): boolean {
|
||||||
|
return this.matchKeyword(flow.request.method) || this.matchKeyword(flow.request.method.toLowerCase())
|
||||||
|
}
|
||||||
|
|
||||||
|
private matchCode(flow: Flow): boolean {
|
||||||
|
if (!flow.response) return false
|
||||||
|
return this.matchKeyword(flow.response.statusCode.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
private _matchHeader(header: Header): boolean {
|
||||||
|
return Object.entries(header).some(([key, vals]) => {
|
||||||
|
return [key].concat(vals).some(text => this.matchKeyword(text))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private matchReqHeader(flow: Flow): boolean {
|
||||||
|
return this._matchHeader(flow.request.header)
|
||||||
|
}
|
||||||
|
|
||||||
|
private matchResHeader(flow: Flow): boolean {
|
||||||
|
if (!flow.response) return false
|
||||||
|
return this._matchHeader(flow.response.header)
|
||||||
|
}
|
||||||
|
|
||||||
|
private matchHeader(flow: Flow): boolean {
|
||||||
|
return this.matchReqHeader(flow) || this.matchResHeader(flow)
|
||||||
|
}
|
||||||
|
|
||||||
|
private matchReqBody(flow: Flow): boolean {
|
||||||
|
const body = flow.requestBody()
|
||||||
|
if (!body) return false
|
||||||
|
return this.matchKeyword(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
private matchResBody(flow: Flow): boolean {
|
||||||
|
const body = flow.responseBody()
|
||||||
|
if (!body) return false
|
||||||
|
return this.matchKeyword(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
private matchBody(flow: Flow): boolean {
|
||||||
|
return this.matchReqBody(flow) || this.matchResBody(flow)
|
||||||
|
}
|
||||||
|
|
||||||
|
private matchAll(flow: Flow): boolean {
|
||||||
|
return this.matchUrl(flow) || this.matchMethod(flow) || this.matchHeader(flow) || this.matchBody(flow)
|
||||||
|
}
|
||||||
|
|
||||||
|
private matchKeyword(text: string): boolean {
|
||||||
|
if (!this.keyword) return true
|
||||||
|
if (!text) return false
|
||||||
|
if (this.keyword instanceof RegExp) return this.keyword.test(text)
|
||||||
|
return text.includes(this.keyword)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue