feat: Enhance cache display and setting in proxy configuration (#10751)

* feat: Enhance caching options for proxy configuration

* fix: typo

* feat: Update caching and directive handling in proxy configuration

* feat: Update default cache time and unit to improve caching configuration

* feat: Implement RemoveCorsOption method to streamline CORS directive removal

* feat: Enhance cache display and initialization in proxy configuration

* refactor: Clean up AddBrowserCache and RemoveCache methods by removing commented-out code
This commit is contained in:
KOMATA 2025-10-24 18:17:51 +08:00 committed by GitHub
parent 08ebbee328
commit 1ef4803954
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 163 additions and 73 deletions

View file

@ -1739,19 +1739,28 @@ func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error)
location.UpdateDirective("proxy_pass", []string{req.ProxyPass})
location.UpdateDirective("proxy_set_header", []string{"Host", req.ProxyHost})
location.ChangePath(req.Modifier, req.Match)
// Server Cache Settings
if req.Cache {
if err = openProxyCache(website); err != nil {
return
}
location.AddCache(req.CacheTime, req.CacheUnit, fmt.Sprintf("proxy_cache_zone_of_%s", website.Alias), req.ServerCacheTime, req.ServerCacheUnit)
location.AddServerCache(fmt.Sprintf("proxy_cache_zone_of_%s", website.Alias), req.ServerCacheTime, req.ServerCacheUnit)
} else {
location.RemoveCache(fmt.Sprintf("proxy_cache_zone_of_%s", website.Alias))
location.RemoveServerCache(fmt.Sprintf("proxy_cache_zone_of_%s", website.Alias))
}
// Browser Cache Settings
if req.CacheTime != 0 {
location.AddBrowserCache(req.CacheTime, req.CacheUnit)
} else {
location.RemoveBrowserCache()
}
// Content Replace Settings
if len(req.Replaces) > 0 {
location.AddSubFilter(req.Replaces)
} else {
location.RemoveSubFilter()
}
// SSL Settings
if req.SNI {
location.UpdateDirective("proxy_ssl_server_name", []string{"on"})
if req.ProxySSLName != "" {
@ -1760,6 +1769,7 @@ func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error)
} else {
location.UpdateDirective("proxy_ssl_server_name", []string{"off"})
}
// CORS Settings
if req.Cors {
location.UpdateDirective("add_header", []string{"Access-Control-Allow-Origin", req.AllowOrigins, "always"})
if req.AllowMethods != "" {
@ -1780,7 +1790,7 @@ func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error)
if req.Preflight {
location.AddCorsOption()
} else {
location.RemoveDirectiveByFullParams("if", []string{"(", "$request_method", "=", "'OPTIONS'", ")"})
location.RemoveCorsOption()
}
} else {
location.RemoveDirective("add_header", []string{"Access-Control-Allow-Origin"})

View file

@ -253,7 +253,7 @@ func (l *Location) ChangePath(Modifier string, Match string) {
l.Match = Match
}
func (l *Location) AddCache(cacheTime int, cacheUint, cacheKey string, serverCacheTime int, serverCacheUint string) {
func (l *Location) AddBrowserCache(cacheTime int, cacheUint string) {
l.RemoveDirective("add_header", []string{"Cache-Control", "no-cache"})
l.RemoveDirectiveByFullParams("if", []string{"(", "$uri", "~*", `"\.(gif|png|jpg|css|js|woff|woff2)$"`, ")"})
l.RemoveDirectiveByFullParams("if", []string{"(", "$uri", "~*", `"\.(gif|png|jpg|css|js|woff|woff2|jpeg|svg|webp|avif)$"`, ")"})
@ -271,28 +271,36 @@ func (l *Location) AddCache(cacheTime int, cacheUint, cacheKey string, serverCac
newDir.Block = block
directives = append(directives, newDir)
l.Directives = directives
l.CacheTime = cacheTime
l.CacheUint = cacheUint
}
func (l *Location) AddServerCache(cacheKey string, serverCacheTime int, serverCacheUint string) {
l.UpdateDirective("proxy_ignore_headers", []string{"Set-Cookie", "Cache-Control", "expires"})
l.UpdateDirective("proxy_cache", []string{cacheKey})
l.UpdateDirective("proxy_cache_key", []string{"$host$uri$is_args$args"})
l.UpdateDirective("proxy_cache_valid", []string{"200", "304", "301", "302", strconv.Itoa(serverCacheTime) + serverCacheUint})
l.Cache = true
l.CacheTime = cacheTime
l.CacheUint = cacheUint
l.ServerCacheTime = serverCacheTime
l.ServerCacheUint = serverCacheUint
}
func (l *Location) RemoveCache(cacheKey string) {
func (l *Location) RemoveBrowserCache() {
l.RemoveDirectiveByFullParams("if", []string{"(", "$uri", "~*", `"\.(gif|png|jpg|css|js|woff|woff2)$"`, ")"})
l.RemoveDirectiveByFullParams("if", []string{"(", "$uri", "~*", `"\.(gif|png|jpg|css|js|woff|woff2|jpeg|svg|webp|avif)$"`, ")"})
l.RemoveDirective("proxy_ignore_headers", []string{"Set-Cookie"})
l.UpdateDirective("add_header", []string{"Cache-Control", "no-cache"})
l.CacheTime = 0
l.CacheUint = ""
}
func (l *Location) RemoveServerCache(cacheKey string) {
l.RemoveDirective("proxy_ignore_headers", []string{"Set-Cookie", "Cache-Control", "expires"})
l.RemoveDirective("proxy_cache", []string{cacheKey})
l.RemoveDirective("proxy_cache_key", []string{"$host$uri$is_args$args"})
l.RemoveDirective("proxy_cache_valid", []string{"200"})
l.UpdateDirective("add_header", []string{"Cache-Control", "no-cache"})
l.CacheTime = 0
l.CacheUint = ""
l.Cache = false
l.ServerCacheTime = 0
l.ServerCacheUint = ""
}
func (l *Location) AddSubFilter(subFilters map[string]string) {
@ -315,6 +323,7 @@ func (l *Location) RemoveSubFilter() {
}
func (l *Location) AddCorsOption() {
l.RemoveCorsOption()
newDir := &Directive{
Name: "if",
Parameters: []string{"(", "$request_method", "=", "'OPTIONS'", ")"},
@ -342,3 +351,7 @@ func (l *Location) AddCorsOption() {
directives = append(directives, newDir)
l.Directives = directives
}
func (l *Location) RemoveCorsOption() {
l.RemoveDirectiveByFullParams("if", []string{"(", "$request_method", "=", "'OPTIONS'", ")"})
}

View file

@ -413,6 +413,7 @@ export namespace Website {
allowHeaders: string;
allowCredentials: boolean;
preflight: boolean;
browserCache?: boolean;
}
export interface ProxReplace {

View file

@ -2496,7 +2496,8 @@ const message = {
'The password is asymmetrically encrypted and cannot be echoed. Editing needs to reset the password',
antiLeech: 'Anti-leech',
extends: 'Extension',
browserCache: 'Cache',
browserCache: 'Browser Cache',
serverCache: 'Server Cache',
leechLog: 'Record anti-leech log',
accessDomain: 'Allowed domains',
leechReturn: 'Response resource',

View file

@ -2483,6 +2483,7 @@ const message = {
antiLeech: 'Anti-hotlink',
extends: 'Extensiones',
browserCache: 'Caché de navegador',
serverCache: 'Caché del servidor',
leechLog: 'Registrar logs anti-hotlink',
accessDomain: 'Dominios permitidos',
leechReturn: 'Recurso de respuesta',

View file

@ -2410,6 +2410,7 @@ const message = {
antiLeech: '反リーチ',
extends: '拡大',
browserCache: 'キャッシュ',
serverCache: 'サーバーキャッシュ',
leechLog: '反リーチログを記録します',
accessDomain: '許可されたドメイン',
leechReturn: '応答リソース',

View file

@ -2367,6 +2367,7 @@ const message = {
antiLeech: '링크 차단',
extends: '확장',
browserCache: '캐시',
serverCache: '서버 캐시',
leechLog: '링크 차단 로그 기록',
accessDomain: '허용된 도메인',
leechReturn: '응답 리소스',

View file

@ -2467,6 +2467,7 @@ const message = {
antiLeech: 'Anti-leech',
extends: 'Pelanjutan',
browserCache: 'Cache',
serverCache: 'Cache Pelayan',
leechLog: 'Rekod log anti-leech',
accessDomain: 'Domain yang dibenarkan',
leechReturn: 'Sumber tindak balas',

View file

@ -2470,6 +2470,7 @@ const message = {
antiLeech: 'Anti-leech',
extends: 'Extensão',
browserCache: 'Cache',
serverCache: 'Cache do servidor',
leechLog: 'Registrar log anti-leech',
accessDomain: 'Domínios permitidos',
leechReturn: 'Recurso de resposta',

View file

@ -2469,6 +2469,7 @@ const message = {
antiLeech: 'Анти-лич',
extends: 'Расширение',
browserCache: 'Кэш',
serverCache: 'Кэш сервера',
leechLog: 'Записывать лог анти-лича',
accessDomain: 'Разрешенные домены',
leechReturn: 'Ответ ресурса',

View file

@ -2529,6 +2529,7 @@ const message = {
antiLeech: 'Sömürü karşıtı',
extends: 'Uzantı',
browserCache: 'Önbellek',
serverCache: 'Sunucu önbelleği',
leechLog: 'Sömürü karşıtı günlüğü kaydet',
accessDomain: 'İzin verilen alan adları',
leechReturn: 'Yanıt kaynağı',

View file

@ -2322,6 +2322,7 @@ const message = {
antiLeech: '防盜鏈',
extends: '副檔名',
browserCache: '瀏覽器快取',
serverCache: '伺服器快取',
leechLog: '記錄防盜鏈日誌',
accessDomain: '允許的域名',
leechReturn: '響應資源',

View file

@ -2315,6 +2315,7 @@ const message = {
antiLeech: '防盗链',
extends: '扩展名',
browserCache: '浏览器缓存',
serverCache: '服务器缓存',
leechLog: '记录防盗链日志',
accessDomain: '允许的域名',
leechReturn: '响应资源',

View file

@ -74,51 +74,89 @@
<el-tab-pane :label="$t('website.advancedSettings')" name="advanced">
<el-divider content-position="left">{{ $t('website.cacheSettings') }}</el-divider>
<!-- Server Cache Control -->
<div class="flex justify-between items-center py-3">
<div class="flex flex-col gap-1">
<span class="font-medium">{{ $t('website.enableCache') }}</span>
<span class="font-medium">{{ $t('website.serverCache') }}</span>
</div>
<el-switch v-model="proxy.cache" @change="changeCache(proxy.cache)" size="large" />
<el-button-group>
<el-button
:type="proxy.cache ? 'primary' : 'default'"
@click="changeServerCache(true)"
size="small"
>
{{ $t('commons.button.enable') }}
</el-button>
<el-button
:type="!proxy.cache ? 'primary' : 'default'"
@click="changeServerCache(false)"
size="small"
>
{{ $t('commons.button.disable') }}
</el-button>
</el-button-group>
</div>
<el-collapse-transition>
<div v-if="proxy.cache" class="mt-4">
<el-row :gutter="16">
<el-col :span="12">
<el-form-item :label="$t('website.browserCacheTime')" prop="cacheTime">
<el-input v-model.number="proxy.cacheTime" maxlength="15">
<template #append>
<el-select v-model="proxy.cacheUnit" class="!w-24">
<el-option
v-for="(unit, index) in Units"
:key="index"
:label="unit.label"
:value="unit.value"
/>
</el-select>
</template>
</el-input>
<span class="input-help">{{ $t('website.browserCacheTimeHelper') }}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="$t('website.serverCacheTime')" prop="serverCacheTime">
<el-input v-model.number="proxy.serverCacheTime" maxlength="15">
<template #append>
<el-select v-model="proxy.serverCacheUnit" class="!w-24">
<el-option
v-for="(unit, index) in Units"
:key="index"
:label="unit.label"
:value="unit.value"
/>
</el-select>
</template>
</el-input>
<span class="input-help">{{ $t('website.serverCacheTimeHelper') }}</span>
</el-form-item>
</el-col>
</el-row>
<div v-if="proxy.cache" class="mt-4 mb-6">
<el-form-item :label="$t('website.serverCacheTime')" prop="serverCacheTime">
<el-input v-model.number="proxy.serverCacheTime" maxlength="15" class="!w-64">
<template #append>
<el-select v-model="proxy.serverCacheUnit" class="!w-24">
<el-option
v-for="(unit, index) in Units"
:key="index"
:label="unit.label"
:value="unit.value"
/>
</el-select>
</template>
</el-input>
<span class="input-help">{{ $t('website.serverCacheTimeHelper') }}</span>
</el-form-item>
</div>
</el-collapse-transition>
<!-- Browser Cache Control -->
<div class="flex justify-between items-center py-3">
<div class="flex flex-col gap-1">
<span class="font-medium">{{ $t('website.browserCache') }}</span>
</div>
<el-button-group>
<el-button
:type="proxy.browserCache ? 'primary' : 'default'"
@click="changeBrowserCache(true)"
size="small"
>
{{ $t('commons.button.enable') }}
</el-button>
<el-button
:type="!proxy.browserCache ? 'primary' : 'default'"
@click="changeBrowserCache(false)"
size="small"
>
{{ $t('commons.button.disable') }}
</el-button>
</el-button-group>
</div>
<el-collapse-transition>
<div v-if="proxy.browserCache" class="mt-4 mb-6">
<el-form-item :label="$t('website.browserCacheTime')" prop="cacheTime">
<el-input v-model.number="proxy.cacheTime" maxlength="15" class="!w-64">
<template #append>
<el-select v-model="proxy.cacheUnit" class="!w-24">
<el-option
v-for="(unit, index) in Units"
:key="index"
:label="unit.label"
:value="unit.value"
/>
</el-select>
</template>
</el-input>
<span class="input-help">{{ $t('website.browserCacheTimeHelper') }}</span>
</el-form-item>
</div>
</el-collapse-transition>
@ -219,8 +257,8 @@ const initData = (): Website.ProxyConfig => ({
operate: 'create',
enable: true,
cache: false,
cacheTime: 1,
cacheUnit: 'm',
cacheTime: 4,
cacheUnit: 'h',
name: '',
modifier: '',
match: '/',
@ -234,6 +272,7 @@ const initData = (): Website.ProxyConfig => ({
proxySSLName: '',
serverCacheTime: 10,
serverCacheUnit: 'm',
browserCache: false,
cors: false,
allowOrigins: '*',
allowMethods: 'GET,POST,OPTIONS,PUT,DELETE',
@ -255,6 +294,11 @@ const acceptParams = (proxyParam: Website.ProxyConfig) => {
proxy.value = proxyParam;
activeTab.value = 'basic';
// Initialize browserCache based on cacheTime value
if (proxy.value.browserCache === undefined) {
proxy.value.browserCache = proxy.value.cacheTime > 0;
}
const res = getProtocolAndHost(proxyParam.proxyPass);
if (res != null) {
proxy.value.proxyProtocol = res.protocol;
@ -271,20 +315,28 @@ const acceptParams = (proxyParam: Website.ProxyConfig) => {
}
};
const changeCache = (cache: boolean) => {
const changeServerCache = (cache: boolean) => {
proxy.value.cache = cache;
if (cache) {
proxy.value.cacheTime = 1;
proxy.value.cacheUnit = 'm';
proxy.value.serverCacheTime = 10;
proxy.value.serverCacheUnit = 'm';
} else {
proxy.value.cacheTime = 0;
proxy.value.cacheUnit = '';
proxy.value.serverCacheTime = 0;
proxy.value.serverCacheUnit = '';
}
};
const changeBrowserCache = (cache: boolean) => {
proxy.value.browserCache = cache;
if (cache) {
proxy.value.cacheTime = 4;
proxy.value.cacheUnit = 'h';
} else {
proxy.value.cacheTime = 0;
proxy.value.cacheUnit = '';
}
};
const addReplaces = () => {
replaces.value.push({ key: '', value: '' });
};

View file

@ -12,10 +12,17 @@
<el-table-column :label="$t('website.proxyPass')" prop="proxyPass"></el-table-column>
<el-table-column :label="$t('website.cache')" prop="cache">
<template #default="{ row }">
<el-switch v-model="row.cache" @change="changeCache(row)" :disabled="!row.enable"></el-switch>
<el-tag :type="row.cacheTime > 0 ? 'success' : 'info'">
{{ $t('website.browserCache') + ':' }}
{{ row.cacheTime > 0 ? row.cacheTime + row.cacheUnit : $t('setting.sslDisable') }}
</el-tag>
<el-tag class="ml-2" :type="row.serverCacheTime > 0 ? 'success' : 'info'">
{{ $t('website.serverCache') + ':' }}
{{ row.serverCacheTime > 0 ? row.serverCacheTime + row.serverCacheUnit : $t('setting.sslDisable') }}
</el-tag>
</template>
</el-table-column>
<el-table-column :label="$t('commons.table.status')" prop="enable">
<el-table-column :label="$t('commons.table.status')" prop="enable" width="100">
<template #default="{ row }">
<Status :status="row.enable ? 'enable' : 'disable'" @click="opProxy(row)" :operate="true" />
</template>
@ -102,8 +109,8 @@ const initData = (id: number): Website.ProxyConfig => ({
operate: 'create',
enable: true,
cache: false,
cacheTime: 1,
cacheUnit: 'm',
cacheTime: 0,
cacheUnit: '',
name: '',
modifier: '',
match: '/',
@ -113,6 +120,12 @@ const initData = (id: number): Website.ProxyConfig => ({
proxySSLName: '',
serverCacheTime: 10,
serverCacheUnit: 'm',
cors: false,
allowOrigins: '',
allowMethods: '',
allowHeaders: '',
allowCredentials: false,
preflight: false,
});
const openCreate = () => {
@ -150,15 +163,6 @@ const deleteProxy = async (proxyConfig: Website.ProxyConfig) => {
});
};
const changeCache = (proxyConfig: Website.ProxyConfig) => {
proxyConfig.operate = 'edit';
if (proxyConfig.cache) {
proxyConfig.cacheTime = 1;
proxyConfig.cacheUnit = 'm';
}
submit(proxyConfig);
};
const submit = async (proxyConfig: Website.ProxyConfig) => {
loading.value = true;
operateProxyConfig(proxyConfig)