From 2b7ec9ffe12255eba2e158b8d1f37721c8b2fbb7 Mon Sep 17 00:00:00 2001 From: CityFun <31820853+zhengkunwang223@users.noreply.github.com> Date: Fri, 8 Aug 2025 16:59:49 +0800 Subject: [PATCH] feat: Reverse proxy supports configuring server caching (#9914) --- agent/app/dto/request/website.go | 34 +++++++------ agent/app/service/website.go | 6 ++- agent/utils/nginx/components/location.go | 50 +++++++++++++------ frontend/src/api/interface/website.ts | 2 + frontend/src/lang/modules/en.ts | 6 +++ frontend/src/lang/modules/ja.ts | 6 +++ frontend/src/lang/modules/ko.ts | 6 +++ frontend/src/lang/modules/ms.ts | 6 +++ frontend/src/lang/modules/pt-br.ts | 6 +++ frontend/src/lang/modules/ru.ts | 6 +++ frontend/src/lang/modules/tr.ts | 6 +++ frontend/src/lang/modules/zh-Hant.ts | 4 ++ frontend/src/lang/modules/zh.ts | 4 ++ .../config/basic/proxy/create/index.vue | 40 +++++++++++---- 14 files changed, 141 insertions(+), 41 deletions(-) diff --git a/agent/app/dto/request/website.go b/agent/app/dto/request/website.go index 2e8567b2c..bf27d511e 100644 --- a/agent/app/dto/request/website.go +++ b/agent/app/dto/request/website.go @@ -203,22 +203,24 @@ type WebsiteUpdateDirPermission struct { } type WebsiteProxyConfig struct { - ID uint `json:"id" validate:"required"` - Operate string `json:"operate" validate:"required"` - Enable bool `json:"enable" ` - Cache bool `json:"cache" ` - CacheTime int `json:"cacheTime" ` - CacheUnit string `json:"cacheUnit"` - Name string `json:"name" validate:"required"` - Modifier string `json:"modifier"` - Match string `json:"match" validate:"required"` - ProxyPass string `json:"proxyPass" validate:"required"` - ProxyHost string `json:"proxyHost" validate:"required"` - Content string `json:"content"` - FilePath string `json:"filePath"` - Replaces map[string]string `json:"replaces"` - SNI bool `json:"sni"` - ProxySSLName string `json:"proxySSLName"` + ID uint `json:"id" validate:"required"` + Operate string `json:"operate" validate:"required"` + Enable bool `json:"enable" ` + Cache bool `json:"cache" ` + CacheTime int `json:"cacheTime"` + CacheUnit string `json:"cacheUnit"` + ServerCacheTime int `json:"serverCacheTime"` + ServerCacheUnit string `json:"serverCacheUnit"` + Name string `json:"name" validate:"required"` + Modifier string `json:"modifier"` + Match string `json:"match" validate:"required"` + ProxyPass string `json:"proxyPass" validate:"required"` + ProxyHost string `json:"proxyHost" validate:"required"` + Content string `json:"content"` + FilePath string `json:"filePath"` + Replaces map[string]string `json:"replaces"` + SNI bool `json:"sni"` + ProxySSLName string `json:"proxySSLName"` } type WebsiteProxyReq struct { diff --git a/agent/app/service/website.go b/agent/app/service/website.go index 5e6500c8f..33cdf83eb 100644 --- a/agent/app/service/website.go +++ b/agent/app/service/website.go @@ -1651,7 +1651,7 @@ func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error) if err = openProxyCache(website); err != nil { return } - location.AddCache(req.CacheTime, req.CacheUnit, fmt.Sprintf("proxy_cache_zone_of_%s", website.Alias)) + location.AddCache(req.CacheTime, req.CacheUnit, 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)) } @@ -1811,6 +1811,10 @@ func (w WebsiteService) GetProxies(id uint) (res []request.WebsiteProxyConfig, e proxyConfig.CacheTime = location.CacheTime proxyConfig.CacheUnit = location.CacheUint } + if location.ServerCacheTime > 0 { + proxyConfig.ServerCacheTime = location.ServerCacheTime + proxyConfig.ServerCacheUnit = location.ServerCacheUint + } proxyConfig.Match = location.Match proxyConfig.Modifier = location.Modifier proxyConfig.ProxyHost = location.Host diff --git a/agent/utils/nginx/components/location.go b/agent/utils/nginx/components/location.go index 0436905d0..3cd518537 100644 --- a/agent/utils/nginx/components/location.go +++ b/agent/utils/nginx/components/location.go @@ -8,18 +8,20 @@ import ( ) type Location struct { - Modifier string - Match string - Cache bool - ProxyPass string - Host string - CacheTime int - CacheUint string - Comment string - Directives []IDirective - Line int - Parameters []string - Replaces map[string]string + Modifier string + Match string + Cache bool + ProxyPass string + Host string + CacheTime int + CacheUint string + Comment string + Directives []IDirective + Line int + Parameters []string + Replaces map[string]string + ServerCacheTime int + ServerCacheUint string } func (l *Location) GetCodeBlock() string { @@ -67,6 +69,22 @@ func NewLocation(directive IDirective) *Location { } } } + case "proxy_cache_valid": + timeParam := params[len(params)-1] + re := regexp.MustCompile(`^(\d+)(\w+)$`) + matches := re.FindStringSubmatch(timeParam) + if matches == nil { + continue + } + + cacheTime, err := strconv.Atoi(matches[1]) + if err != nil { + continue + } + unit := matches[2] + + location.ServerCacheTime = cacheTime + location.ServerCacheUint = unit case "sub_filter": if location.Replaces == nil { location.Replaces = make(map[string]string, 0) @@ -186,13 +204,14 @@ func (l *Location) ChangePath(Modifier string, Match string) { l.Match = Match } -func (l *Location) AddCache(cacheTime int, cacheUint, cacheKey string) { +func (l *Location) AddCache(cacheTime int, cacheUint, cacheKey string, serverCacheTime int, serverCacheUint string) { l.RemoveDirective("add_header", []string{"Cache-Control", "no-cache"}) l.RemoveDirective("if", []string{"(", "$uri", "~*", `"\.(gif|png|jpg|css|js|woff|woff2)$"`, ")"}) + l.RemoveDirective("if", []string{"(", "$uri", "~*", `"\.(gif|png|jpg|css|js|woff|woff2|jpeg|svg|webp|avif)$"`, ")"}) directives := l.GetDirectives() newDir := &Directive{ Name: "if", - Parameters: []string{"(", "$uri", "~*", `"\.(gif|png|jpg|css|js|woff|woff2)$"`, ")"}, + Parameters: []string{"(", "$uri", "~*", `"\.(gif|png|jpg|css|js|woff|woff2|jpeg|svg|webp|avif)$"`, ")"}, Block: &Block{}, } block := &Block{} @@ -206,7 +225,7 @@ func (l *Location) AddCache(cacheTime int, cacheUint, cacheKey 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", "10m"}) + l.UpdateDirective("proxy_cache_valid", []string{"200", "304", "301", "302", strconv.Itoa(serverCacheTime) + serverCacheUint}) l.Cache = true l.CacheTime = cacheTime l.CacheUint = cacheUint @@ -214,6 +233,7 @@ func (l *Location) AddCache(cacheTime int, cacheUint, cacheKey string) { func (l *Location) RemoveCache(cacheKey string) { l.RemoveDirective("if", []string{"(", "$uri", "~*", `"\.(gif|png|jpg|css|js|woff|woff2)$"`, ")"}) + l.RemoveDirective("if", []string{"(", "$uri", "~*", `"\.(gif|png|jpg|css|js|woff|woff2|jpeg|svg|webp|avif)$"`, ")"}) l.RemoveDirective("proxy_ignore_headers", []string{"Set-Cookie"}) l.RemoveDirective("proxy_cache", []string{cacheKey}) l.RemoveDirective("proxy_cache_key", []string{"$host$uri$is_args$args"}) diff --git a/frontend/src/api/interface/website.ts b/frontend/src/api/interface/website.ts index 26922f39e..bef6ff6aa 100644 --- a/frontend/src/api/interface/website.ts +++ b/frontend/src/api/interface/website.ts @@ -388,6 +388,8 @@ export namespace Website { cache: boolean; cacheTime: number; cacheUnit: string; + serverCacheTime: number; + serverCacheUnit: string; name: string; modifier: string; match: string; diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 44b4cd2c7..c9d321c9c 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -2505,6 +2505,12 @@ const message = { openBaseDir: 'Prevent Cross-Site Attacks', openBaseDirHelper: 'open_basedir is used to restrict the PHP file access path, which helps prevent cross-site access and enhance security', + serverCacheTime: 'Server Cache Time', + serverCacheTimeHelper: + 'The time a request is cached on the server. During this period, identical requests will return the cached result directly without requesting the origin server.', + browserCacheTime: 'Browser Cache Time', + browserCacheTimeHelper: + 'The time static resources are cached locally in the browser, reducing redundant requests. Users will use the local cache directly before it expires when refreshing the page.', }, php: { short_open_tag: 'Short tag support', diff --git a/frontend/src/lang/modules/ja.ts b/frontend/src/lang/modules/ja.ts index 400f62eff..619802888 100644 --- a/frontend/src/lang/modules/ja.ts +++ b/frontend/src/lang/modules/ja.ts @@ -2421,6 +2421,12 @@ const message = { openBaseDir: 'クロスサイト攻撃を防ぐ', openBaseDirHelper: 'open_basedir は PHP ファイルのアクセスパスを制限し、クロスサイトアクセスを防ぎセキュリティを向上させるために使用されます', + serverCacheTime: 'サーバーキャッシュ時間', + serverCacheTimeHelper: + 'リクエストがサーバー上でキャッシュされる時間。この期間中、同一のリクエストはオリジンサーバーにリクエストせず、キャッシュされた結果を直接返します。', + browserCacheTime: 'ブラウザキャッシュ時間', + browserCacheTimeHelper: + '静的リソースがブラウザのローカルにキャッシュされる時間、冗長なリクエストを減らします。有効期限前にユーザーがページをリフレッシュすると、ローカルキャッシュが直接使用されます。', }, php: { short_open_tag: '短いタグサポート', diff --git a/frontend/src/lang/modules/ko.ts b/frontend/src/lang/modules/ko.ts index 3c638b88c..eeb9edf9d 100644 --- a/frontend/src/lang/modules/ko.ts +++ b/frontend/src/lang/modules/ko.ts @@ -2379,6 +2379,12 @@ const message = { openBaseDir: '사이트 간 공격 방지', openBaseDirHelper: 'open_basedir는 PHP 파일 액세스 경로를 제한하여 사이트 간 액세스를 방지하고 보안을 향상시키는 데 사용됩니다', + serverCacheTime: '서버 캐시 시간', + serverCacheTimeHelper: + '요청이 서버에서 캐시되는 시간. 이 기간 동안 동일한 요청은 원본 서버에 요청하지 않고 캐시된 결과를 직접 반환합니다.', + browserCacheTime: '브라우저 캐시 시간', + browserCacheTimeHelper: + '정적 리소스가 브라우저 로컬에 캐시되는 시간, 중복 요청을 줄입니다. 유효기간 전에 사용자가 페이지를 새로 고치면 로컬 캐시가 직접 사용됩니다.', }, php: { short_open_tag: '짧은 태그 지원', diff --git a/frontend/src/lang/modules/ms.ts b/frontend/src/lang/modules/ms.ts index d4e0c60ca..1b8f4162b 100644 --- a/frontend/src/lang/modules/ms.ts +++ b/frontend/src/lang/modules/ms.ts @@ -2476,6 +2476,12 @@ const message = { openBaseDir: 'Pencegahan Serangan Lintas Situs', openBaseDirHelper: 'open_basedir digunakan untuk membatasi jalur akses file PHP, yang membantu mencegah akses lintas situs dan meningkatkan keamanan', + serverCacheTime: 'Masa Cache Pelayan', + serverCacheTimeHelper: + 'Masa permintaan di-cache di pelayan. Semasa tempoh ini, permintaan yang sama akan mengembalikan hasil cache terus tanpa meminta pelayan asal.', + browserCacheTime: 'Masa Cache Pelayar', + browserCacheTimeHelper: + 'Masa sumber statik di-cache secara tempatan di pelayar, mengurangkan permintaan berulang. Pengguna akan menggunakan cache tempatan secara langsung sebelum tamat tempoh semasa menyegarkan halaman.', }, php: { short_open_tag: 'Sokongan tag pendek', diff --git a/frontend/src/lang/modules/pt-br.ts b/frontend/src/lang/modules/pt-br.ts index d64e490eb..9c8420799 100644 --- a/frontend/src/lang/modules/pt-br.ts +++ b/frontend/src/lang/modules/pt-br.ts @@ -2477,6 +2477,12 @@ const message = { openBaseDir: 'Prevenir Ataques entre Sites', openBaseDirHelper: 'open_basedir é usado para restringir o caminho de acesso a arquivos PHP, ajudando a prevenir acesso entre sites e aumentar a segurança', + serverCacheTime: 'Tempo de Cache do Servidor', + serverCacheTimeHelper: + 'O tempo que uma requisição é armazenada em cache no servidor. Durante este período, requisições idênticas retornarão o resultado em cache diretamente, sem pedir ao servidor de origem.', + browserCacheTime: 'Tempo de Cache do Navegador', + browserCacheTimeHelper: + 'O tempo que os recursos estáticos são armazenados em cache localmente no navegador, reduzindo requisições redundantes. Os usuários usarão o cache local diretamente antes de expirar ao atualizar a página.', }, php: { short_open_tag: 'Suporte para short tags', diff --git a/frontend/src/lang/modules/ru.ts b/frontend/src/lang/modules/ru.ts index 00eed9a1e..add1c566d 100644 --- a/frontend/src/lang/modules/ru.ts +++ b/frontend/src/lang/modules/ru.ts @@ -2474,6 +2474,12 @@ const message = { openBaseDir: 'Предотвращение межсайтовых атак', openBaseDirHelper: 'open_basedir используется для ограничения пути доступа к файлам PHP, что помогает предотвратить межсайтовый доступ и повысить безопасность', + serverCacheTime: 'Время кеширования на сервере', + serverCacheTimeHelper: + 'Время, в течение которого запрос кешируется на сервере. В этот период идентичные запросы будут возвращать кешированный результат напрямую, без запроса к исходному серверу.', + browserCacheTime: 'Время кеширования в браузере', + browserCacheTimeHelper: + 'Время, в течение которого статические ресурсы кешируются локально в браузере, уменьшая повторные запросы. Пользователи будут использовать локальный кеш напрямую, если срок его действия не истек при обновлении страницы.', }, php: { short_open_tag: 'Поддержка коротких тегов', diff --git a/frontend/src/lang/modules/tr.ts b/frontend/src/lang/modules/tr.ts index 570d694df..e441c47d6 100644 --- a/frontend/src/lang/modules/tr.ts +++ b/frontend/src/lang/modules/tr.ts @@ -2536,6 +2536,12 @@ const message = { openBaseDir: 'Siteler Arası Saldırıları Önle', openBaseDirHelper: 'open_basedir, PHP dosya erişim yolunu kısıtlamak için kullanılır, bu siteler arası erişimi önlemeye ve güvenliği artırmaya yardımcı olur', + serverCacheTime: 'Sunucu Önbellek Süresi', + serverCacheTimeHelper: + 'Bir isteğin sunucuda önbelleğe alındığı süre. Bu süre boyunca, aynı istekler önbelleğe alınmış sonucu doğrudan döndürür ve kaynak sunucuya istekte bulunmaz.', + browserCacheTime: 'Tarayıcı Önbellek Süresi', + browserCacheTimeHelper: + 'Statik kaynakların tarayıcıda yerel olarak önbelleğe alındığı süre, tekrarlayan istekleri azaltır. Kullanıcılar süre dolmadan önce sayfayı yenilediğinde yerel önbelleği doğrudan kullanır.', }, php: { short_open_tag: 'Kısa etiket desteği', diff --git a/frontend/src/lang/modules/zh-Hant.ts b/frontend/src/lang/modules/zh-Hant.ts index f900fe310..16bc7e01a 100644 --- a/frontend/src/lang/modules/zh-Hant.ts +++ b/frontend/src/lang/modules/zh-Hant.ts @@ -2339,6 +2339,10 @@ const message = { westCN: '西部數碼', openBaseDir: '防跨站攻擊', openBaseDirHelper: 'open_basedir 用於限制 PHP 文件訪問路徑,有助於防止跨站訪問和提升安全性', + serverCacheTime: '伺服器緩存時間', + serverCacheTimeHelper: '請求在伺服器端緩存的時間,到期前相同請求會直接返回緩存結果,不再請求源站。', + browserCacheTime: '瀏覽器緩存時間', + browserCacheTimeHelper: '靜態資源在瀏覽器本地緩存的時間,減少重複請求。到期前用戶刷新頁面會直接使用本地緩存。', }, php: { short_open_tag: '短標簽支持', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index d8a7383b9..879ddbe44 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -2328,6 +2328,10 @@ const message = { westCN: '西部数码', openBaseDir: '防跨站攻击', openBaseDirHelper: 'open_basedir 用于限制 PHP 文件访问路径,有助于防止跨站访问和提升安全性', + serverCacheTime: '服务器缓存时间', + serverCacheTimeHelper: '请求在服务器端缓存的时间,到期前相同请求会直接返回缓存结果,不再请求源站。', + browserCacheTime: '浏览器缓存时间', + browserCacheTimeHelper: '静态资源在浏览器本地缓存的时间,减少重复请求。到期前用户刷新页面会直接使用本地缓存。', }, php: { short_open_tag: '短标签支持', diff --git a/frontend/src/views/website/website/config/basic/proxy/create/index.vue b/frontend/src/views/website/website/config/basic/proxy/create/index.vue index 432999ac4..3a9de8d74 100644 --- a/frontend/src/views/website/website/config/basic/proxy/create/index.vue +++ b/frontend/src/views/website/website/config/basic/proxy/create/index.vue @@ -16,17 +16,10 @@ - - - {{ $t('website.sniHelper') }} - - - - - + + {{ $t('website.browserCacheTimeHelper') }} + + + + + + {{ $t('website.serverCacheTimeHelper') }} + + + + {{ $t('website.sniHelper') }} + + + @@ -140,6 +156,8 @@ const initData = (): Website.ProxyConfig => ({ proxyProtocol: 'http://', sni: false, proxySSLName: '', + serverCacheTime: 10, + serverCacheUnit: 'm', }); let proxy = ref(initData()); const replaces = ref([]); @@ -174,9 +192,13 @@ const changeCache = (cache: boolean) => { 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 = ''; } };