简化缓存条件设置

This commit is contained in:
GoEdgeLab
2022-09-03 18:14:34 +08:00
parent 4a9ba125fa
commit 34eca0a59f
9 changed files with 189 additions and 21 deletions

View File

@@ -5,6 +5,7 @@ import (
"github.com/TeaOSLab/EdgeAdmin/internal/utils" "github.com/TeaOSLab/EdgeAdmin/internal/utils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs" "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"github.com/iwind/TeaGo/actions" "github.com/iwind/TeaGo/actions"
) )
@@ -27,19 +28,43 @@ func (this *CreatePopupAction) RunGet(params struct {
func (this *CreatePopupAction) RunPost(params struct { func (this *CreatePopupAction) RunPost(params struct {
CacheRefJSON []byte CacheRefJSON []byte
CondType string
CondJSON []byte
Must *actions.Must Must *actions.Must
}) { }) {
var cacheRef = &serverconfigs.HTTPCacheRef{} var cacheRef = &serverconfigs.HTTPCacheRef{}
err := json.Unmarshal(params.CacheRefJSON, cacheRef) err := json.Unmarshal(params.CacheRefJSON, cacheRef)
if err != nil { if err != nil {
this.ErrorPage(err) this.Fail("解析条件出错:" + err.Error() + ", JSON: " + string(params.CacheRefJSON))
return return
} }
if len(params.CondJSON) > 0 {
var cond = &shared.HTTPRequestCond{}
err = json.Unmarshal(params.CondJSON, cond)
if err != nil {
this.Fail("解析条件出错:" + err.Error() + ", JSON: " + string(params.CondJSON))
return
}
cond.Type = params.CondType
cacheRef.SimpleCond = cond
// 将组合条件置为空
cacheRef.Conds = &shared.HTTPRequestCondsConfig{}
}
err = cacheRef.Init()
if err != nil {
this.Fail("解析条件出错:" + err.Error())
return
}
if len(cacheRef.Key) == 0 { if len(cacheRef.Key) == 0 {
this.Fail("请输入缓存Key") this.Fail("请输入缓存Key")
} }
if cacheRef.Conds == nil || len(cacheRef.Conds.Groups) == 0 { if (cacheRef.Conds == nil || len(cacheRef.Conds.Groups) == 0) && cacheRef.SimpleCond == nil {
this.Fail("请填写匹配条件分组") this.Fail("请填写匹配条件分组")
} }

View File

@@ -3,6 +3,12 @@ Vue.component("http-cache-ref-box", {
props: ["v-cache-ref", "v-is-reverse"], props: ["v-cache-ref", "v-is-reverse"],
mounted: function () { mounted: function () {
this.$refs.variablesDescriber.update(this.ref.key) this.$refs.variablesDescriber.update(this.ref.key)
if (this.ref.simpleCond != null) {
this.changeCondType(this.ref.simpleCond.type)
this.condCategory = "simple"
} else if (this.ref.conds != null && this.ref.conds.groups != null) {
this.condCategory = "complex"
}
}, },
data: function () { data: function () {
let ref = this.vCacheRef let ref = this.vCacheRef
@@ -18,7 +24,8 @@ Vue.component("http-cache-ref-box", {
skipCacheControlValues: ["private", "no-cache", "no-store"], skipCacheControlValues: ["private", "no-cache", "no-store"],
skipSetCookie: true, skipSetCookie: true,
enableRequestCachePragma: false, enableRequestCachePragma: false,
conds: null, conds: null, // 复杂条件
simpleCond: null, // 简单条件
allowChunkedEncoding: true, allowChunkedEncoding: true,
allowPartialContent: false, allowPartialContent: false,
enableIfNoneMatch: false, enableIfNoneMatch: false,
@@ -50,9 +57,19 @@ Vue.component("http-cache-ref-box", {
if (ref.minSize == null) { if (ref.minSize == null) {
ref.minSize = {count: 0, unit: "kb"} ref.minSize = {count: 0, unit: "kb"}
} }
let condType = "url-extension"
let condComponent = window.REQUEST_COND_COMPONENTS.$find(function (k, v) {
return v.type == "url-extension"
})
return { return {
ref: ref, ref: ref,
moreOptionsVisible: false moreOptionsVisible: false,
condCategory: "simple", // 条件分类simple|complex
condType: condType,
condComponent: condComponent,
components: window.REQUEST_COND_COMPONENTS
} }
}, },
methods: { methods: {
@@ -70,6 +87,7 @@ Vue.component("http-cache-ref-box", {
}, },
changeConds: function (v) { changeConds: function (v) {
this.ref.conds = v this.ref.conds = v
this.ref.simpleCond = null
}, },
changeStatusList: function (list) { changeStatusList: function (list) {
let result = [] let result = []
@@ -92,15 +110,46 @@ Vue.component("http-cache-ref-box", {
}, },
changeExpiresTime: function (expiresTime) { changeExpiresTime: function (expiresTime) {
this.ref.expiresTime = expiresTime this.ref.expiresTime = expiresTime
},
// 切换条件类型
changeCondCategory: function (condCategory) {
this.condCategory = condCategory
},
changeCondType: function (condType) {
let def = this.components.$find(function (k, component) {
return component.type == condType
})
if (def != null) {
this.condComponent = def
}
} }
}, },
template: `<tbody> template: `<tbody>
<tr> <tr v-if="condCategory == 'simple'">
<td class="title color-border">条件类型 *</td>
<td>
<select class="ui dropdown auto-width" name="condType" v-model="condType" @change="changeCondType(condType)">
<option value="url-extension">URL扩展名</option>
<option value="url-prefix">URL前缀</option>
<option value="url-eq-index">首页</option>
<option value="url-eq">URL精准匹配</option>
<option value="url-regexp">URL正则匹配</option>
</select>
<p class="comment"><a href="" @click.prevent="changeCondCategory('complex')">切换到复杂条件 &raquo;</a></p>
</td>
</tr>
<tr v-if="condCategory == 'simple'">
<td class="color-border">{{condComponent.paramsTitle}} *</td>
<td>
<component :is="condComponent.component" :v-cond="ref.simpleCond"></component>
</td>
</tr>
<tr v-if="condCategory == 'complex'">
<td class="title">匹配条件分组 *</td> <td class="title">匹配条件分组 *</td>
<td> <td>
<http-request-conds-box :v-conds="ref.conds" @change="changeConds"></http-request-conds-box> <http-request-conds-box :v-conds="ref.conds" @change="changeConds"></http-request-conds-box>
<p class="comment"><a href="" @click.prevent="changeCondCategory('simple')">&laquo; 切换到简单条件</a></p>
<input type="hidden" name="cacheRefJSON" :value="JSON.stringify(ref)"/>
</td> </td>
</tr> </tr>
<tr v-show="!vIsReverse"> <tr v-show="!vIsReverse">
@@ -208,5 +257,8 @@ Vue.component("http-cache-ref-box", {
<p class="comment">特殊情况下才需要开启,可能会降低缓存命中率。</p> <p class="comment">特殊情况下才需要开启,可能会降低缓存命中率。</p>
</td> </td>
</tr> </tr>
<tr v-show="false">
<td colspan="2"><input type="hidden" name="cacheRefJSON" :value="JSON.stringify(ref)"/></td>
</tr>
</tbody>` </tbody>`
}) })

View File

@@ -43,7 +43,10 @@ Vue.component("http-cache-refs-box", {
</tr> </tr>
<tr v-for="(cacheRef, index) in refs"> <tr v-for="(cacheRef, index) in refs">
<td :class="{'color-border': cacheRef.conds.connector == 'and', disabled: !cacheRef.isOn}" :style="{'border-left':cacheRef.isReverse ? '1px #db2828 solid' : ''}"> <td :class="{'color-border': cacheRef.conds.connector == 'and', disabled: !cacheRef.isOn}" :style="{'border-left':cacheRef.isReverse ? '1px #db2828 solid' : ''}">
<http-request-conds-view :v-conds="cacheRef.conds" :class="{disabled: !cacheRef.isOn}"></http-request-conds-view> <http-request-conds-view :v-conds="cacheRef.conds" :class="{disabled: !cacheRef.isOn}" v-if="cacheRef.conds != null && cacheRef.conds.groups != null"></http-request-conds-view>
<http-request-cond-view :v-cond="cacheRef.simpleCond" v-if="cacheRef.simpleCond != null"></http-request-cond-view>
<!-- 特殊参数 -->
<grey-label v-if="cacheRef.minSize != null && cacheRef.minSize.count > 0"> <grey-label v-if="cacheRef.minSize != null && cacheRef.minSize.count > 0">
{{cacheRef.minSize.count}}{{cacheRef.minSize.unit}} {{cacheRef.minSize.count}}{{cacheRef.minSize.unit}}
<span v-if="cacheRef.maxSize != null && cacheRef.maxSize.count > 0">- {{cacheRef.maxSize.count}}{{cacheRef.maxSize.unit}}</span> <span v-if="cacheRef.maxSize != null && cacheRef.maxSize.count > 0">- {{cacheRef.maxSize.count}}{{cacheRef.maxSize.unit}}</span>

View File

@@ -98,7 +98,7 @@ Vue.component("http-cache-refs-config-box", {
resp.data.cacheRef.id = that.refs[index].id resp.data.cacheRef.id = that.refs[index].id
Vue.set(that.refs, index, resp.data.cacheRef) Vue.set(that.refs, index, resp.data.cacheRef)
that.change() that.change()
that.$refs.cacheRef[index].updateConds(resp.data.cacheRef.conds) that.$refs.cacheRef[index].updateConds(resp.data.cacheRef.conds, resp.data.cacheRef.simpleCond)
that.$refs.cacheRef[index].notifyChange() that.$refs.cacheRef[index].notifyChange()
} }
}) })
@@ -186,7 +186,10 @@ Vue.component("http-cache-refs-config-box", {
<tr> <tr>
<td style="text-align: center;"><i class="icon bars handle grey"></i> </td> <td style="text-align: center;"><i class="icon bars handle grey"></i> </td>
<td :class="{'color-border': cacheRef.conds.connector == 'and', disabled: !cacheRef.isOn}" :style="{'border-left':cacheRef.isReverse ? '1px #db2828 solid' : ''}"> <td :class="{'color-border': cacheRef.conds.connector == 'and', disabled: !cacheRef.isOn}" :style="{'border-left':cacheRef.isReverse ? '1px #db2828 solid' : ''}">
<http-request-conds-view :v-conds="cacheRef.conds" ref="cacheRef" :class="{disabled: !cacheRef.isOn}"></http-request-conds-view> <http-request-conds-view :v-conds="cacheRef.conds" ref="cacheRef" :class="{disabled: !cacheRef.isOn}" v-if="cacheRef.conds != null && cacheRef.conds.groups != null"></http-request-conds-view>
<http-request-cond-view :v-cond="cacheRef.simpleCond" ref="cacheRef" v-if="cacheRef.simpleCond != null"></http-request-cond-view>
<!-- 特殊参数 -->
<grey-label v-if="cacheRef.minSize != null && cacheRef.minSize.count > 0"> <grey-label v-if="cacheRef.minSize != null && cacheRef.minSize.count > 0">
{{cacheRef.minSize.count}}{{cacheRef.minSize.unit}} {{cacheRef.minSize.count}}{{cacheRef.minSize.unit}}
<span v-if="cacheRef.maxSize != null && cacheRef.maxSize.count > 0">- {{cacheRef.maxSize.count}}{{cacheRef.maxSize.unit}}</span> <span v-if="cacheRef.maxSize != null && cacheRef.maxSize.count > 0">- {{cacheRef.maxSize.count}}{{cacheRef.maxSize.unit}}</span>

View File

@@ -206,7 +206,7 @@ Vue.component("http-cond-url-prefix", {
template: `<div> template: `<div>
<input type="hidden" name="condJSON" :value="JSON.stringify(cond)"/> <input type="hidden" name="condJSON" :value="JSON.stringify(cond)"/>
<input type="text" v-model="cond.value"/> <input type="text" v-model="cond.value"/>
<p class="comment">URL前缀有此前缀的URL都将会被匹配通常以<code-label>/</code-label>开头,比如<code-label>/static</code-label>。</p> <p class="comment">URL前缀有此前缀的URL都将会被匹配通常以<code-label>/</code-label>开头,比如<code-label>/static</code-label>、<code-label>/images</code-label>,不需要带域名。</p>
</div>` </div>`
}) })
@@ -236,7 +236,37 @@ Vue.component("http-cond-url-not-prefix", {
template: `<div> template: `<div>
<input type="hidden" name="condJSON" :value="JSON.stringify(cond)"/> <input type="hidden" name="condJSON" :value="JSON.stringify(cond)"/>
<input type="text" v-model="cond.value"/> <input type="text" v-model="cond.value"/>
<p class="comment">要排除的URL前缀有此前缀的URL都将会被匹配通常以<code-label>/</code-label>开头,比如<code-label>/static</code-label>。</p> <p class="comment">要排除的URL前缀有此前缀的URL都将会被匹配通常以<code-label>/</code-label>开头,比如<code-label>/static</code-label>、<code-label>/images</code-label>,不需要带域名。</p>
</div>`
})
// 首页
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: `<div>
<input type="hidden" name="condJSON" :value="JSON.stringify(cond)"/>
<input type="text" v-model="cond.value" disabled="disabled" style="background: #eee"/>
<p class="comment">检查URL路径是为<code-label>/</code-label>,不需要带域名。</p>
</div>` </div>`
}) })
@@ -266,7 +296,7 @@ Vue.component("http-cond-url-eq", {
template: `<div> template: `<div>
<input type="hidden" name="condJSON" :value="JSON.stringify(cond)"/> <input type="hidden" name="condJSON" :value="JSON.stringify(cond)"/>
<input type="text" v-model="cond.value"/> <input type="text" v-model="cond.value"/>
<p class="comment">完整的URL路径通常以<code-label>/</code-label>开头,比如<code-label>/static/ui.js</code-label>并不包含域名部分。</p> <p class="comment">完整的URL路径通常以<code-label>/</code-label>开头,比如<code-label>/static/ui.js</code-label>不需要带域名。</p>
</div>` </div>`
}) })
@@ -296,7 +326,7 @@ Vue.component("http-cond-url-not-eq", {
template: `<div> template: `<div>
<input type="hidden" name="condJSON" :value="JSON.stringify(cond)"/> <input type="hidden" name="condJSON" :value="JSON.stringify(cond)"/>
<input type="text" v-model="cond.value"/> <input type="text" v-model="cond.value"/>
<p class="comment">要排除的完整的URL路径通常以<code-label>/</code-label>开头,比如<code-label>/static/ui.js</code-label>并不包含域名部分。</p> <p class="comment">要排除的完整的URL路径通常以<code-label>/</code-label>开头,比如<code-label>/static/ui.js</code-label>不需要带域名。</p>
</div>` </div>`
}) })
@@ -326,7 +356,7 @@ Vue.component("http-cond-url-regexp", {
template: `<div> template: `<div>
<input type="hidden" name="condJSON" :value="JSON.stringify(cond)"/> <input type="hidden" name="condJSON" :value="JSON.stringify(cond)"/>
<input type="text" v-model="cond.value"/> <input type="text" v-model="cond.value"/>
<p class="comment">匹配URL的正则表达式比如<code-label>^/static/(.*).js$</code-label>。</p> <p class="comment">匹配URL的正则表达式比如<code-label>^/static/(.*).js$</code-label>,不需要带域名。</p>
</div>` </div>`
}) })
@@ -356,7 +386,7 @@ Vue.component("http-cond-url-not-regexp", {
template: `<div> template: `<div>
<input type="hidden" name="condJSON" :value="JSON.stringify(cond)"/> <input type="hidden" name="condJSON" :value="JSON.stringify(cond)"/>
<input type="text" v-model="cond.value"/> <input type="text" v-model="cond.value"/>
<p class="comment"><strong>不要</strong>匹配URL的正则表达式意即只要匹配成功则排除此条件比如<code-label>^/static/(.*).js$</code-label>。</p> <p class="comment"><strong>不要</strong>匹配URL的正则表达式意即只要匹配成功则排除此条件比如<code-label>^/static/(.*).js$</code-label>,不需要带域名。</p>
</div>` </div>`
}) })

View File

@@ -0,0 +1,38 @@
Vue.component("http-request-cond-view", {
props: ["v-cond"],
data: function () {
return {
cond: this.vCond,
components: window.REQUEST_COND_COMPONENTS
}
},
methods: {
typeName: function (cond) {
let c = this.components.$find(function (k, v) {
return v.type == cond.type
})
if (c != null) {
return c.name;
}
return cond.param + " " + cond.operator
},
updateConds: function (conds, simpleCond) {
for (let k in simpleCond) {
if (simpleCond.hasOwnProperty(k)) {
this.cond[k] = simpleCond[k]
}
}
},
notifyChange: function () {
}
},
template: `<div style="margin-bottom: 0.5em">
<span class="ui label small basic">
<var v-if="cond.type.length == 0 || cond.type == 'params'" style="font-style: normal">{{cond.param}} <var>{{cond.operator}}</var></var>
<var v-if="cond.type.length > 0 && cond.type != 'params'" style="font-style: normal">{{typeName(cond)}}: </var>
{{cond.value}}
<sup v-if="cond.isCaseInsensitive" title="不区分大小写"><i class="icon info small"></i></sup>
</span>
</div>`
})

View File

@@ -9,6 +9,9 @@ Vue.component("http-request-conds-box", {
groups: [] groups: []
} }
} }
if (conds.groups == null) {
conds.groups = []
}
return { return {
conds: conds, conds: conds,
components: window.REQUEST_COND_COMPONENTS components: window.REQUEST_COND_COMPONENTS

View File

@@ -10,6 +10,9 @@ Vue.component("http-request-conds-view", {
groups: [] groups: []
} }
} }
if (conds.groups == null) {
conds.groups = []
}
let that = this let that = this
conds.groups.forEach(function (group) { conds.groups.forEach(function (group) {
@@ -43,12 +46,14 @@ Vue.component("http-request-conds-view", {
}, },
notifyChange: function () { notifyChange: function () {
let that = this let that = this
this.initConds.groups.forEach(function (group) { if (this.initConds.groups != null) {
group.conds.forEach(function (cond) { this.initConds.groups.forEach(function (group) {
cond.typeName = that.typeName(cond) group.conds.forEach(function (cond) {
cond.typeName = that.typeName(cond)
})
}) })
}) this.$forceUpdate()
this.$forceUpdate() }
} }
}, },
template: `<div> template: `<div>

View File

@@ -7,6 +7,15 @@
"paramsTitle": "扩展名列表", "paramsTitle": "扩展名列表",
"isRequest": true "isRequest": true
}, },
{
"type": "url-eq-index",
"name": "首页",
"description": "检查URL路径是为\"/\"",
"component": "http-cond-url-eq-index",
"paramsTitle": "URL完整路径",
"isRequest": true,
"caseInsensitive": false
},
{ {
"type": "url-prefix", "type": "url-prefix",
"name": "URL前缀", "name": "URL前缀",