// URL扩展名条件 Vue.component("http-cond-url-extension", { props: ["v-cond"], data: function () { let cond = { isRequest: true, param: "${requestPathExtension}", operator: "in", value: "[]" } if (this.vCond != null && this.vCond.param == cond.param) { cond.value = this.vCond.value } let extensions = [] try { extensions = JSON.parse(cond.value) } catch (e) { } return { cond: cond, extensions: extensions, // TODO 可以拖动排序 isAdding: false, addingExt: "" } }, watch: { extensions: function () { this.cond.value = JSON.stringify(this.extensions) } }, methods: { addExt: function () { this.isAdding = !this.isAdding if (this.isAdding) { let that = this setTimeout(function () { that.$refs.addingExt.focus() }, 100) } }, cancelAdding: function () { this.isAdding = false this.addingExt = "" }, confirmAdding: function () { // TODO 做更详细的校验 // TODO 如果有重复的则提示之 if (this.addingExt.length == 0) { return } if (this.addingExt[0] != ".") { this.addingExt = "." + this.addingExt } this.addingExt = this.addingExt.replace(/\s+/g, "").toLowerCase() this.extensions.push(this.addingExt) // 清除状态 this.cancelAdding() }, removeExt: function (index) { this.extensions.$remove(index) } }, template: `
{{ext}}

扩展名需要包含点(.)符号,例如.jpg.png之类。

` }) // URL扩展名条件 Vue.component("http-cond-url-not-extension", { props: ["v-cond"], data: function () { let cond = { isRequest: true, param: "${requestPathExtension}", operator: "not in", value: "[]" } if (this.vCond != null && this.vCond.param == cond.param) { cond.value = this.vCond.value } let extensions = [] try { extensions = JSON.parse(cond.value) } catch (e) { } return { cond: cond, extensions: extensions, // TODO 可以拖动排序 isAdding: false, addingExt: "" } }, watch: { extensions: function () { this.cond.value = JSON.stringify(this.extensions) } }, methods: { addExt: function () { this.isAdding = !this.isAdding if (this.isAdding) { let that = this setTimeout(function () { that.$refs.addingExt.focus() }, 100) } }, cancelAdding: function () { this.isAdding = false this.addingExt = "" }, confirmAdding: function () { // TODO 做更详细的校验 // TODO 如果有重复的则提示之 if (this.addingExt.length == 0) { return } if (this.addingExt[0] != ".") { this.addingExt = "." + this.addingExt } this.addingExt = this.addingExt.replace(/\s+/g, "").toLowerCase() this.extensions.push(this.addingExt) // 清除状态 this.cancelAdding() }, removeExt: function (index) { this.extensions.$remove(index) } }, template: `
{{ext}}

扩展名需要包含点(.)符号,例如.jpg.png之类。

` }) // 根据URL前缀 Vue.component("http-cond-url-prefix", { props: ["v-cond"], data: function () { let cond = { isRequest: true, param: "${requestPath}", operator: "prefix", value: "", isCaseInsensitive: false } if (this.vCond != null && typeof (this.vCond.value) == "string") { cond.value = this.vCond.value } return { cond: cond } }, methods: { changeCaseInsensitive: function (isCaseInsensitive) { this.cond.isCaseInsensitive = isCaseInsensitive } }, template: `

URL前缀,有此前缀的URL都将会被匹配,通常以/开头,比如/static/images,不需要带域名。

` }) Vue.component("http-cond-url-not-prefix", { props: ["v-cond"], data: function () { let cond = { isRequest: true, param: "${requestPath}", operator: "prefix", value: "", isReverse: true, isCaseInsensitive: false } if (this.vCond != null && typeof this.vCond.value == "string") { cond.value = this.vCond.value } return { cond: cond } }, methods: { changeCaseInsensitive: function (isCaseInsensitive) { this.cond.isCaseInsensitive = isCaseInsensitive } }, template: `

要排除的URL前缀,有此前缀的URL都将会被匹配,通常以/开头,比如/static/images,不需要带域名。

` }) // 首页 Vue.component("http-cond-url-eq-index", { props: ["v-cond"], data: function () { let cond = { isRequest: true, param: "${requestPath}", operator: "eq", value: "/", isCaseInsensitive: false } if (this.vCond != null && typeof this.vCond.value == "string") { cond.value = this.vCond.value } return { cond: cond } }, methods: { changeCaseInsensitive: function (isCaseInsensitive) { this.cond.isCaseInsensitive = isCaseInsensitive } }, template: `

检查URL路径是为/,不需要带域名。

` }) // URL精准匹配 Vue.component("http-cond-url-eq", { props: ["v-cond"], data: function () { let cond = { isRequest: true, param: "${requestPath}", operator: "eq", value: "", isCaseInsensitive: false } if (this.vCond != null && typeof this.vCond.value == "string") { cond.value = this.vCond.value } return { cond: cond } }, methods: { changeCaseInsensitive: function (isCaseInsensitive) { this.cond.isCaseInsensitive = isCaseInsensitive } }, template: `

完整的URL路径,通常以/开头,比如/static/ui.js,不需要带域名。

` }) Vue.component("http-cond-url-not-eq", { props: ["v-cond"], data: function () { let cond = { isRequest: true, param: "${requestPath}", operator: "eq", value: "", isReverse: true, isCaseInsensitive: false } if (this.vCond != null && typeof this.vCond.value == "string") { cond.value = this.vCond.value } return { cond: cond } }, methods: { changeCaseInsensitive: function (isCaseInsensitive) { this.cond.isCaseInsensitive = isCaseInsensitive } }, template: `

要排除的完整的URL路径,通常以/开头,比如/static/ui.js,不需要带域名。

` }) // URL正则匹配 Vue.component("http-cond-url-regexp", { props: ["v-cond"], data: function () { let cond = { isRequest: true, param: "${requestPath}", operator: "regexp", value: "", isCaseInsensitive: false } if (this.vCond != null && typeof this.vCond.value == "string") { cond.value = this.vCond.value } return { cond: cond } }, methods: { changeCaseInsensitive: function (isCaseInsensitive) { this.cond.isCaseInsensitive = isCaseInsensitive } }, template: `

匹配URL的正则表达式,比如^/static/(.*).js$,不需要带域名。

` }) // 排除URL正则匹配 Vue.component("http-cond-url-not-regexp", { props: ["v-cond"], data: function () { let cond = { isRequest: true, param: "${requestPath}", operator: "not regexp", value: "", isCaseInsensitive: false } if (this.vCond != null && typeof this.vCond.value == "string") { cond.value = this.vCond.value } return { cond: cond } }, methods: { changeCaseInsensitive: function (isCaseInsensitive) { this.cond.isCaseInsensitive = isCaseInsensitive } }, template: `

不要匹配URL的正则表达式,意即只要匹配成功则排除此条件,比如^/static/(.*).js$,不需要带域名。

` }) // User-Agent正则匹配 Vue.component("http-cond-user-agent-regexp", { props: ["v-cond"], data: function () { let cond = { isRequest: true, param: "${userAgent}", operator: "regexp", value: "", isCaseInsensitive: false } if (this.vCond != null && typeof this.vCond.value == "string") { cond.value = this.vCond.value } return { cond: cond } }, methods: { changeCaseInsensitive: function (isCaseInsensitive) { this.cond.isCaseInsensitive = isCaseInsensitive } }, template: `

匹配User-Agent的正则表达式,比如Android|iPhone

` }) // User-Agent正则不匹配 Vue.component("http-cond-user-agent-not-regexp", { props: ["v-cond"], data: function () { let cond = { isRequest: true, param: "${userAgent}", operator: "not regexp", value: "", isCaseInsensitive: false } if (this.vCond != null && typeof this.vCond.value == "string") { cond.value = this.vCond.value } return { cond: cond } }, methods: { changeCaseInsensitive: function (isCaseInsensitive) { this.cond.isCaseInsensitive = isCaseInsensitive } }, template: `

匹配User-Agent的正则表达式,比如Android|iPhone,如果匹配,则排除此条件。

` }) // 根据MimeType Vue.component("http-cond-mime-type", { props: ["v-cond"], data: function () { let cond = { isRequest: false, param: "${response.contentType}", operator: "mime type", value: "[]" } if (this.vCond != null && this.vCond.param == cond.param) { cond.value = this.vCond.value } return { cond: cond, mimeTypes: JSON.parse(cond.value), // TODO 可以拖动排序 isAdding: false, addingMimeType: "" } }, watch: { mimeTypes: function () { this.cond.value = JSON.stringify(this.mimeTypes) } }, methods: { addMimeType: function () { this.isAdding = !this.isAdding if (this.isAdding) { let that = this setTimeout(function () { that.$refs.addingMimeType.focus() }, 100) } }, cancelAdding: function () { this.isAdding = false this.addingMimeType = "" }, confirmAdding: function () { // TODO 做更详细的校验 // TODO 如果有重复的则提示之 if (this.addingMimeType.length == 0) { return } this.addingMimeType = this.addingMimeType.replace(/\s+/g, "") this.mimeTypes.push(this.addingMimeType) // 清除状态 this.cancelAdding() }, removeMimeType: function (index) { this.mimeTypes.$remove(index) } }, template: `
{{mimeType}}

服务器返回的内容的MimeType,比如text/htmlimage/*等。

` }) // 参数匹配 Vue.component("http-cond-params", { props: ["v-cond"], mounted: function () { let cond = this.vCond if (cond == null) { return } this.operator = cond.operator // stringValue if (["regexp", "not regexp", "eq", "not", "prefix", "suffix", "contains", "not contains", "eq ip", "gt ip", "gte ip", "lt ip", "lte ip", "ip range"].$contains(cond.operator)) { this.stringValue = cond.value return } // numberValue if (["eq int", "eq float", "gt", "gte", "lt", "lte", "mod 10", "ip mod 10", "mod 100", "ip mod 100"].$contains(cond.operator)) { this.numberValue = cond.value return } // modValue if (["mod", "ip mod"].$contains(cond.operator)) { let pieces = cond.value.split(",") this.modDivValue = pieces[0] if (pieces.length > 1) { this.modRemValue = pieces[1] } return } // stringValues let that = this if (["in", "not in", "file ext", "mime type"].$contains(cond.operator)) { try { let arr = JSON.parse(cond.value) if (arr != null && (arr instanceof Array)) { arr.forEach(function (v) { that.stringValues.push(v) }) } } catch (e) { } return } // versionValue if (["version range"].$contains(cond.operator)) { let pieces = cond.value.split(",") this.versionRangeMinValue = pieces[0] if (pieces.length > 1) { this.versionRangeMaxValue = pieces[1] } return } }, data: function () { let cond = { isRequest: true, param: "", operator: window.REQUEST_COND_OPERATORS[0].op, value: "", isCaseInsensitive: false } if (this.vCond != null) { cond = this.vCond } return { cond: cond, operators: window.REQUEST_COND_OPERATORS, operator: window.REQUEST_COND_OPERATORS[0].op, operatorDescription: window.REQUEST_COND_OPERATORS[0].description, variables: window.REQUEST_VARIABLES, variable: "", // 各种类型的值 stringValue: "", numberValue: "", modDivValue: "", modRemValue: "", stringValues: [], versionRangeMinValue: "", versionRangeMaxValue: "" } }, methods: { changeVariable: function () { let v = this.cond.param if (v == null) { v = "" } this.cond.param = v + this.variable }, changeOperator: function () { let that = this this.operators.forEach(function (v) { if (v.op == that.operator) { that.operatorDescription = v.description } }) this.cond.operator = this.operator // 移动光标 let box = document.getElementById("variables-value-box") if (box != null) { setTimeout(function () { let input = box.getElementsByTagName("INPUT") if (input.length > 0) { input[0].focus() } }, 100) } }, changeStringValues: function (v) { this.stringValues = v this.cond.value = JSON.stringify(v) } }, watch: { stringValue: function (v) { this.cond.value = v }, numberValue: function (v) { // TODO 校验数字 this.cond.value = v }, modDivValue: function (v) { if (v.length == 0) { return } let div = parseInt(v) if (isNaN(div)) { div = 1 } this.modDivValue = div this.cond.value = div + "," + this.modRemValue }, modRemValue: function (v) { if (v.length == 0) { return } let rem = parseInt(v) if (isNaN(rem)) { rem = 0 } this.modRemValue = rem this.cond.value = this.modDivValue + "," + rem }, versionRangeMinValue: function (v) { this.cond.value = this.versionRangeMinValue + "," + this.versionRangeMaxValue }, versionRangeMaxValue: function (v) { this.cond.value = this.versionRangeMinValue + "," + this.versionRangeMaxValue } }, template: ` 参数值

其中可以使用变量,类似于\${requestPath},也可以是多个变量的组合。

操作符

{{operatorDescription}}

对比值

要匹配的正则表达式,比如^/static/(.+).js

要对比的数字。

参数值除以10的余数,在0-9之间。

参数值除以100的余数,在0-99之间。

除:
余:

和参数值一致的字符串。

和参数值不一致的字符串。

参数值的前缀。

参数值的后缀为此字符串。

参数值包含此字符串。

参数值不包含此字符串。

添加参数值列表。

添加参数值列表。

添加扩展名列表,比如pnghtml,不包括点。

添加MimeType列表,类似于text/htmlimage/*

-

要对比的IP。

参数中IP转换成整数后除以10的余数,在0-9之间。

参数中IP转换成整数后除以100的余数,在0-99之间。

不区分大小写

选中后表示对比时忽略参数值的大小写。

` })