diff --git a/internal/web/actions/default/servers/server/settings/conds/addCondPopup.go b/internal/web/actions/default/servers/server/settings/conds/addCondPopup.go index b752c2a7..a7409887 100644 --- a/internal/web/actions/default/servers/server/settings/conds/addCondPopup.go +++ b/internal/web/actions/default/servers/server/settings/conds/addCondPopup.go @@ -30,7 +30,7 @@ func (this *AddCondPopupAction) RunPost(params struct { condConfig := &shared.HTTPRequestCond{} err := json.Unmarshal(params.CondJSON, condConfig) if err != nil { - this.Fail("解析条件设置时发生了错误:" + err.Error()) + this.Fail("解析条件设置时发生了错误:" + err.Error() + ", JSON: " + string(params.CondJSON)) } err = condConfig.Init() if err != nil { diff --git a/internal/web/actions/default/ui/components.go b/internal/web/actions/default/ui/components.go index f99bad57..f11d6928 100644 --- a/internal/web/actions/default/ui/components.go +++ b/internal/web/actions/default/ui/components.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/conds/condutils" + "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared" "github.com/iwind/TeaGo/Tea" "github.com/iwind/TeaGo/actions" "github.com/iwind/TeaGo/files" @@ -52,13 +53,33 @@ func (this *ComponentsAction) RunGet(params struct{}) { // 条件组件 typesJSON, err := json.Marshal(condutils.ReadAllAvailableCondTypes()) if err != nil { - logs.Println("ComponentsAction: " + err.Error()) + logs.Println("ComponentsAction marshal request cond types failed: " + err.Error()) } else { buffer.WriteString("window.REQUEST_COND_COMPONENTS = ") buffer.Write(typesJSON) buffer.Write([]byte{'\n', '\n'}) } + // 条件操作符 + requestOperatorsJSON, err := json.Marshal(shared.AllRequestOperators()) + if err != nil { + logs.Println("ComponentsAction marshal request operators failed: " + err.Error()) + } else { + buffer.WriteString("window.REQUEST_COND_OPERATORS = ") + buffer.Write(requestOperatorsJSON) + buffer.Write([]byte{'\n', '\n'}) + } + + // 请求变量 + requestVariablesJSON, err := json.Marshal(shared.DefaultRequestVariables()) + if err != nil { + logs.Println("ComponentsAction marshal request variables failed: " + err.Error()) + } else { + buffer.WriteString("window.REQUEST_VARIABLES = ") + buffer.Write(requestVariablesJSON) + buffer.Write([]byte{'\n', '\n'}) + } + componentsData = buffer.Bytes() this.Write(componentsData) } diff --git a/web/public/js/components/server/http-cache-refs-box.js b/web/public/js/components/server/http-cache-refs-box.js index 77797c3d..650e528f 100644 --- a/web/public/js/components/server/http-cache-refs-box.js +++ b/web/public/js/components/server/http-cache-refs-box.js @@ -40,7 +40,6 @@ Vue.component("http-cache-refs-box", { 条件 分组关系 缓存时间 - 操作 @@ -54,10 +53,6 @@ Vue.component("http-cache-refs-box", { {{cacheRef.life.count}} {{timeUnitName(cacheRef.life.unit)}} 不缓存 - - 修改   - 删除 - diff --git a/web/public/js/components/server/http-cache-refs-config-box.js b/web/public/js/components/server/http-cache-refs-config-box.js index 56146e78..d74233b1 100644 --- a/web/public/js/components/server/http-cache-refs-config-box.js +++ b/web/public/js/components/server/http-cache-refs-config-box.js @@ -11,11 +11,7 @@ Vue.component("http-cache-refs-config-box", { } }) }) - that.refs = newRefs - - if (that.vCacheConfig != null) { - that.vCacheConfig.cacheRefs = newRefs - } + that.updateRefs(newRefs) }) }, data: function () { @@ -51,9 +47,32 @@ Vue.component("http-cache-refs-config-box", { width: width + "px", height: height + "px", callback: function (resp) { + let newRef = resp.data.cacheRef + if (newRef.conds == null) { + return + } + that.id++ - resp.data.cacheRef.id = that.id - that.refs.push(resp.data.cacheRef) + newRef.id = that.id + + if (newRef.isReverse) { + let newRefs = [] + let isAdded = false + that.refs.forEach(function (v) { + if (!v.isReverse && !isAdded) { + newRefs.push(newRef) + isAdded = true + } + newRefs.push(v) + }) + if (!isAdded) { + newRefs.push(newRef) + } + + that.updateRefs(newRefs) + } else { + that.refs.push(newRef) + } } }) }, @@ -87,6 +106,12 @@ Vue.component("http-cache-refs-config-box", { that.refs.$remove(index) }) }, + updateRefs: function (newRefs) { + this.refs = newRefs + if (this.vCacheConfig != null) { + this.vCacheConfig.cacheRefs = newRefs + } + }, timeUnitName: function (unit) { switch (unit) { case "ms": diff --git a/web/public/js/components/server/http-cond-definitions.js b/web/public/js/components/server/http-cond-definitions.js index 5aa0a593..23b3b71f 100644 --- a/web/public/js/components/server/http-cond-definitions.js +++ b/web/public/js/components/server/http-cond-definitions.js @@ -311,4 +311,276 @@ Vue.component("http-cond-mime-type", {

服务器返回的内容的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: "" + } + 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之间。

+
+ + +` }) \ No newline at end of file diff --git a/web/public/js/components/server/http-request-conds-box.js b/web/public/js/components/server/http-request-conds-box.js index 2fbba2a6..5bb7de25 100644 --- a/web/public/js/components/server/http-request-conds-box.js +++ b/web/public/js/components/server/http-request-conds-box.js @@ -67,8 +67,8 @@ Vue.component("http-request-conds-box", { - {{cond.param}} {{cond.operator}} - {{typeName(cond)}}: + {{cond.param}} {{cond.operator}} + {{typeName(cond)}}: {{cond.value}} diff --git a/web/public/js/components/server/http-request-conds-view.js b/web/public/js/components/server/http-request-conds-view.js index bd708869..6c9ec40b 100644 --- a/web/public/js/components/server/http-request-conds-view.js +++ b/web/public/js/components/server/http-request-conds-view.js @@ -1,3 +1,4 @@ +// 浏览条件列表 Vue.component("http-request-conds-view", { props: ["v-conds"], data: function () { @@ -54,8 +55,8 @@ Vue.component("http-request-conds-view", {
- {{cond.param}} {{cond.operator}} - {{cond.typeName}}: + {{cond.param}} {{cond.operator}} + {{cond.typeName}}: {{cond.value}} diff --git a/web/public/js/conds/official.json b/web/public/js/conds/official.json index 2941ca09..0d505f76 100644 --- a/web/public/js/conds/official.json +++ b/web/public/js/conds/official.json @@ -31,6 +31,14 @@ "paramsTitle": "正则表达式", "isRequest": true }, + { + "type": "params", + "name": "参数匹配", + "description": "根据参数值进行匹配", + "component": "http-cond-params", + "paramsTitle": "参数配置", + "isRequest": true + }, { "type": "url-not-prefix", "name": "排除:URL前缀", diff --git a/web/views/@default/servers/server/settings/conds/addCondPopup.html b/web/views/@default/servers/server/settings/conds/addCondPopup.html index d51a05bb..525d8dc6 100644 --- a/web/views/@default/servers/server/settings/conds/addCondPopup.html +++ b/web/views/@default/servers/server/settings/conds/addCondPopup.html @@ -15,14 +15,19 @@ {$ end} - + {{paramsTitle}} {$ range .components} - <{$ .Component} v-if="condType == '{$ .Type}'" :v-cond="cond"> + {$if not (eq .Type "params") } + <{$ .Component} v-if="condType == '{$ .Type}'" :v-cond="cond"> + {$end} {$ end} + + + 确定 \ No newline at end of file diff --git a/web/views/@default/servers/server/settings/conds/addGroupPopup.html b/web/views/@default/servers/server/settings/conds/addGroupPopup.html index 950362a0..46504aaa 100644 --- a/web/views/@default/servers/server/settings/conds/addGroupPopup.html +++ b/web/views/@default/servers/server/settings/conds/addGroupPopup.html @@ -11,8 +11,8 @@
- {{cond.param}} {{cond.operator}} - {{typeName(cond)}}: + {{cond.param}} {{cond.operator}} + {{typeName(cond)}}: {{cond.value}} {{group.connector}}