diff --git a/internal/config/config.go b/internal/config/config.go index 5044c94..f515b38 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -76,7 +76,6 @@ func (c *configImpl) Update(newConfig *Config) { // 更新配置 c.MAP = newConfig.MAP c.Compression = newConfig.Compression - c.FixedPaths = newConfig.FixedPaths // 触发回调 for _, callback := range c.onConfigUpdate { diff --git a/internal/config/types.go b/internal/config/types.go index 5413106..901142e 100644 --- a/internal/config/types.go +++ b/internal/config/types.go @@ -8,7 +8,6 @@ import ( type Config struct { MAP map[string]PathConfig `json:"MAP"` // 改为使用PathConfig Compression CompressionConfig `json:"Compression"` - FixedPaths []FixedPathConfig `json:"FixedPaths"` } type PathConfig struct { @@ -30,19 +29,12 @@ type CompressorConfig struct { Level int `json:"Level"` } -type FixedPathConfig struct { - Path string `json:"Path"` - TargetHost string `json:"TargetHost"` - TargetURL string `json:"TargetURL"` -} - // 添加一个辅助方法来处理字符串到 PathConfig 的转换 func (c *Config) UnmarshalJSON(data []byte) error { // 创建一个临时结构来解析原始JSON type TempConfig struct { MAP map[string]json.RawMessage `json:"MAP"` Compression CompressionConfig `json:"Compression"` - FixedPaths []FixedPathConfig `json:"FixedPaths"` } var temp TempConfig @@ -77,7 +69,6 @@ func (c *Config) UnmarshalJSON(data []byte) error { // 复制其他字段 c.Compression = temp.Compression - c.FixedPaths = temp.FixedPaths return nil } diff --git a/internal/handler/cache_admin.go b/internal/handler/cache_admin.go index ce36e9b..3815947 100644 --- a/internal/handler/cache_admin.go +++ b/internal/handler/cache_admin.go @@ -7,16 +7,14 @@ import ( ) type CacheAdminHandler struct { - proxyCache *cache.CacheManager - mirrorCache *cache.CacheManager - fixedPathCache *cache.CacheManager + proxyCache *cache.CacheManager + mirrorCache *cache.CacheManager } -func NewCacheAdminHandler(proxyCache, mirrorCache, fixedPathCache *cache.CacheManager) *CacheAdminHandler { +func NewCacheAdminHandler(proxyCache, mirrorCache *cache.CacheManager) *CacheAdminHandler { return &CacheAdminHandler{ - proxyCache: proxyCache, - mirrorCache: mirrorCache, - fixedPathCache: fixedPathCache, + proxyCache: proxyCache, + mirrorCache: mirrorCache, } } @@ -35,9 +33,8 @@ func (h *CacheAdminHandler) GetCacheStats(w http.ResponseWriter, r *http.Request } stats := map[string]cache.CacheStats{ - "proxy": h.proxyCache.GetStats(), - "mirror": h.mirrorCache.GetStats(), - "fixedPath": h.fixedPathCache.GetStats(), + "proxy": h.proxyCache.GetStats(), + "mirror": h.mirrorCache.GetStats(), } w.Header().Set("Content-Type", "application/json") @@ -52,9 +49,8 @@ func (h *CacheAdminHandler) GetCacheConfig(w http.ResponseWriter, r *http.Reques } configs := map[string]cache.CacheConfig{ - "proxy": h.proxyCache.GetConfig(), - "mirror": h.mirrorCache.GetConfig(), - "fixedPath": h.fixedPathCache.GetConfig(), + "proxy": h.proxyCache.GetConfig(), + "mirror": h.mirrorCache.GetConfig(), } w.Header().Set("Content-Type", "application/json") @@ -69,7 +65,7 @@ func (h *CacheAdminHandler) UpdateCacheConfig(w http.ResponseWriter, r *http.Req } var req struct { - Type string `json:"type"` // "proxy", "mirror" 或 "fixedPath" + Type string `json:"type"` // "proxy", "mirror" Config CacheConfig `json:"config"` // 新的配置 } @@ -84,8 +80,6 @@ func (h *CacheAdminHandler) UpdateCacheConfig(w http.ResponseWriter, r *http.Req targetCache = h.proxyCache case "mirror": targetCache = h.mirrorCache - case "fixedPath": - targetCache = h.fixedPathCache default: http.Error(w, "Invalid cache type", http.StatusBadRequest) return @@ -107,7 +101,7 @@ func (h *CacheAdminHandler) SetCacheEnabled(w http.ResponseWriter, r *http.Reque } var req struct { - Type string `json:"type"` // "proxy", "mirror" 或 "fixedPath" + Type string `json:"type"` // "proxy", "mirror" Enabled bool `json:"enabled"` // true 或 false } @@ -121,8 +115,6 @@ func (h *CacheAdminHandler) SetCacheEnabled(w http.ResponseWriter, r *http.Reque h.proxyCache.SetEnabled(req.Enabled) case "mirror": h.mirrorCache.SetEnabled(req.Enabled) - case "fixedPath": - h.fixedPathCache.SetEnabled(req.Enabled) default: http.Error(w, "Invalid cache type", http.StatusBadRequest) return @@ -139,7 +131,7 @@ func (h *CacheAdminHandler) ClearCache(w http.ResponseWriter, r *http.Request) { } var req struct { - Type string `json:"type"` // "proxy", "mirror", "fixedPath" 或 "all" + Type string `json:"type"` // "proxy", "mirror" 或 "all" } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { @@ -153,16 +145,11 @@ func (h *CacheAdminHandler) ClearCache(w http.ResponseWriter, r *http.Request) { err = h.proxyCache.ClearCache() case "mirror": err = h.mirrorCache.ClearCache() - case "fixedPath": - err = h.fixedPathCache.ClearCache() case "all": err = h.proxyCache.ClearCache() if err == nil { err = h.mirrorCache.ClearCache() } - if err == nil { - err = h.fixedPathCache.ClearCache() - } default: http.Error(w, "Invalid cache type", http.StatusBadRequest) return diff --git a/internal/handler/config.go b/internal/handler/config.go index c6ed9f7..60fb8bb 100644 --- a/internal/handler/config.go +++ b/internal/handler/config.go @@ -118,18 +118,5 @@ func (h *ConfigHandler) validateConfig(cfg *config.Config) error { } } - // 验证FixedPaths配置 - for _, fp := range cfg.FixedPaths { - if fp.Path == "" { - return fmt.Errorf("固定路径不能为空") - } - if fp.TargetURL == "" { - return fmt.Errorf("固定路径 %s 的目标URL不能为空", fp.Path) - } - if _, err := url.Parse(fp.TargetURL); err != nil { - return fmt.Errorf("固定路径 %s 的目标URL无效: %v", fp.Path, err) - } - } - return nil } diff --git a/internal/handler/proxy.go b/internal/handler/proxy.go index 9b148d1..d2995ac 100644 --- a/internal/handler/proxy.go +++ b/internal/handler/proxy.go @@ -40,10 +40,6 @@ var hopHeadersBase = map[string]bool{ "Upgrade": true, } -func init() { - // 移除旧的初始化代码,因为我们直接在 map 字面量中定义了所有值 -} - // ErrorHandler 定义错误处理函数类型 type ErrorHandler func(w http.ResponseWriter, r *http.Request, err error) diff --git a/internal/middleware/fixed_path_proxy.go b/internal/middleware/fixed_path_proxy.go deleted file mode 100644 index a649e19..0000000 --- a/internal/middleware/fixed_path_proxy.go +++ /dev/null @@ -1,165 +0,0 @@ -package middleware - -import ( - "errors" - "io" - "log" - "net/http" - "proxy-go/internal/cache" - "proxy-go/internal/config" - "proxy-go/internal/metrics" - "proxy-go/internal/utils" - "strings" - "syscall" - "time" -) - -type FixedPathConfig struct { - Path string `json:"Path"` - TargetHost string `json:"TargetHost"` - TargetURL string `json:"TargetURL"` -} - -var fixedPathCache *cache.CacheManager - -func init() { - var err error - fixedPathCache, err = cache.NewCacheManager("data/fixed_path_cache") - if err != nil { - log.Printf("[Cache] Failed to initialize fixed path cache manager: %v", err) - } -} - -func FixedPathProxyMiddleware(configs []config.FixedPathConfig) func(http.Handler) http.Handler { - return func(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - startTime := time.Now() - collector := metrics.GetCollector() - collector.BeginRequest() - defer collector.EndRequest() - - // 检查是否匹配任何固定路径 - for _, cfg := range configs { - if strings.HasPrefix(r.URL.Path, cfg.Path) { - // 创建新的请求 - targetPath := strings.TrimPrefix(r.URL.Path, cfg.Path) - targetURL := cfg.TargetURL + targetPath - - // 检查是否可以使用缓存 - if r.Method == http.MethodGet && fixedPathCache != nil { - cacheKey := fixedPathCache.GenerateCacheKey(r) - if item, hit, notModified := fixedPathCache.Get(cacheKey, r); hit { - // 从缓存提供响应 - w.Header().Set("Content-Type", item.ContentType) - if item.ContentEncoding != "" { - w.Header().Set("Content-Encoding", item.ContentEncoding) - } - w.Header().Set("Proxy-Go-Cache", "HIT") - if notModified { - w.WriteHeader(http.StatusNotModified) - return - } - http.ServeFile(w, r, item.FilePath) - collector.RecordRequest(r.URL.Path, http.StatusOK, time.Since(startTime), item.Size, utils.GetClientIP(r), r) - return - } - } - - proxyReq, err := http.NewRequest(r.Method, targetURL, r.Body) - if err != nil { - http.Error(w, "Error creating proxy request", http.StatusInternalServerError) - log.Printf("[Fixed] ERR %s %s -> 500 (%s) create request error from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r)) - return - } - - // 复制原始请求的 header - for key, values := range r.Header { - for _, value := range values { - proxyReq.Header.Add(key, value) - } - } - - // 设置必要的头部 - proxyReq.Host = cfg.TargetHost - proxyReq.Header.Set("Host", cfg.TargetHost) - proxyReq.Header.Set("X-Real-IP", utils.GetClientIP(r)) - proxyReq.Header.Set("X-Scheme", r.URL.Scheme) - - // 发送代理请求 - client := &http.Client{} - resp, err := client.Do(proxyReq) - if err != nil { - http.Error(w, "Error forwarding request", http.StatusBadGateway) - log.Printf("[Fixed] ERR %s %s -> 502 (%s) proxy error from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r)) - return - } - defer resp.Body.Close() - - // 复制响应头 - for key, values := range resp.Header { - for _, value := range values { - w.Header().Add(key, value) - } - } - w.Header().Set("Proxy-Go-Cache", "MISS") - - // 设置响应状态码 - w.WriteHeader(resp.StatusCode) - - var written int64 - // 如果是GET请求且响应成功,使用TeeReader同时写入缓存 - if r.Method == http.MethodGet && resp.StatusCode == http.StatusOK && fixedPathCache != nil { - cacheKey := fixedPathCache.GenerateCacheKey(r) - if cacheFile, err := fixedPathCache.CreateTemp(cacheKey, resp); err == nil { - defer cacheFile.Close() - teeReader := io.TeeReader(resp.Body, cacheFile) - written, err = io.Copy(w, teeReader) - if err == nil { - fixedPathCache.Commit(cacheKey, cacheFile.Name(), resp, written) - } - } else { - written, err = io.Copy(w, resp.Body) - if err != nil && !isConnectionClosed(err) { - log.Printf("[Fixed] ERR %s %s -> write error (%s) from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r)) - } - } - } else { - written, err = io.Copy(w, resp.Body) - if err != nil && !isConnectionClosed(err) { - log.Printf("[Fixed] ERR %s %s -> write error (%s) from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r)) - } - } - - // 记录统计信息 - collector.RecordRequest(r.URL.Path, resp.StatusCode, time.Since(startTime), written, utils.GetClientIP(r), r) - - return - } - } - - // 如果没有匹配的固定路径,继续下一个处理器 - next.ServeHTTP(w, r) - }) - } -} - -func isConnectionClosed(err error) bool { - if err == nil { - return false - } - - // 忽略常见的连接关闭错误 - if errors.Is(err, syscall.EPIPE) || // broken pipe - errors.Is(err, syscall.ECONNRESET) || // connection reset by peer - strings.Contains(err.Error(), "broken pipe") || - strings.Contains(err.Error(), "connection reset by peer") { - return true - } - - return false -} - -// GetFixedPathCache 获取固定路径缓存管理器 -func GetFixedPathCache() *cache.CacheManager { - return fixedPathCache -} diff --git a/main.go b/main.go index 84f274f..17f6dbd 100644 --- a/main.go +++ b/main.go @@ -40,7 +40,6 @@ func main() { // 创建代理处理器 mirrorHandler := handler.NewMirrorProxyHandler() proxyHandler := handler.NewProxyHandler(cfg) - fixedPathCache := middleware.GetFixedPathCache() // 创建处理器链 handlers := []struct { @@ -88,16 +87,16 @@ func main() { case "/admin/api/config/save": proxyHandler.AuthMiddleware(handler.NewConfigHandler(cfg).ServeHTTP)(w, r) case "/admin/api/cache/stats": - proxyHandler.AuthMiddleware(handler.NewCacheAdminHandler(proxyHandler.Cache, mirrorHandler.Cache, fixedPathCache).GetCacheStats)(w, r) + proxyHandler.AuthMiddleware(handler.NewCacheAdminHandler(proxyHandler.Cache, mirrorHandler.Cache).GetCacheStats)(w, r) case "/admin/api/cache/enable": - proxyHandler.AuthMiddleware(handler.NewCacheAdminHandler(proxyHandler.Cache, mirrorHandler.Cache, fixedPathCache).SetCacheEnabled)(w, r) + proxyHandler.AuthMiddleware(handler.NewCacheAdminHandler(proxyHandler.Cache, mirrorHandler.Cache).SetCacheEnabled)(w, r) case "/admin/api/cache/clear": - proxyHandler.AuthMiddleware(handler.NewCacheAdminHandler(proxyHandler.Cache, mirrorHandler.Cache, fixedPathCache).ClearCache)(w, r) + proxyHandler.AuthMiddleware(handler.NewCacheAdminHandler(proxyHandler.Cache, mirrorHandler.Cache).ClearCache)(w, r) case "/admin/api/cache/config": if r.Method == http.MethodGet { - proxyHandler.AuthMiddleware(handler.NewCacheAdminHandler(proxyHandler.Cache, mirrorHandler.Cache, fixedPathCache).GetCacheConfig)(w, r) + proxyHandler.AuthMiddleware(handler.NewCacheAdminHandler(proxyHandler.Cache, mirrorHandler.Cache).GetCacheConfig)(w, r) } else if r.Method == http.MethodPost { - proxyHandler.AuthMiddleware(handler.NewCacheAdminHandler(proxyHandler.Cache, mirrorHandler.Cache, fixedPathCache).UpdateCacheConfig)(w, r) + proxyHandler.AuthMiddleware(handler.NewCacheAdminHandler(proxyHandler.Cache, mirrorHandler.Cache).UpdateCacheConfig)(w, r) } else { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) } @@ -129,18 +128,6 @@ func main() { }, handler: mirrorHandler, }, - // 固定路径处理器 - { - matcher: func(r *http.Request) bool { - for _, fp := range cfg.FixedPaths { - if strings.HasPrefix(r.URL.Path, fp.Path) { - return true - } - } - return false - }, - handler: middleware.FixedPathProxyMiddleware(cfg.FixedPaths)(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})), - }, // 默认代理处理器 { matcher: func(r *http.Request) bool { diff --git a/web/app/dashboard/cache/page.tsx b/web/app/dashboard/cache/page.tsx index cd64083..e1e51f9 100644 --- a/web/app/dashboard/cache/page.tsx +++ b/web/app/dashboard/cache/page.tsx @@ -28,13 +28,11 @@ interface CacheConfig { interface CacheData { proxy: CacheStats mirror: CacheStats - fixedPath: CacheStats } interface CacheConfigs { proxy: CacheConfig mirror: CacheConfig - fixedPath: CacheConfig } function formatBytes(bytes: number) { @@ -133,7 +131,7 @@ export default function CachePage() { return () => clearInterval(interval) }, [fetchStats, fetchConfigs]) - const handleToggleCache = async (type: "proxy" | "mirror" | "fixedPath", enabled: boolean) => { + const handleToggleCache = async (type: "proxy" | "mirror", enabled: boolean) => { try { const token = localStorage.getItem("token") if (!token) { @@ -160,7 +158,7 @@ export default function CachePage() { toast({ title: "成功", - description: `${type === "proxy" ? "代理" : type === "mirror" ? "镜像" : "固定路径"}缓存已${enabled ? "启用" : "禁用"}`, + description: `${type === "proxy" ? "代理" : "镜像"}缓存已${enabled ? "启用" : "禁用"}`, }) fetchStats() @@ -173,7 +171,7 @@ export default function CachePage() { } } - const handleUpdateConfig = async (type: "proxy" | "mirror" | "fixedPath", config: CacheConfig) => { + const handleUpdateConfig = async (type: "proxy" | "mirror", config: CacheConfig) => { try { const token = localStorage.getItem("token") if (!token) { @@ -213,7 +211,7 @@ export default function CachePage() { } } - const handleClearCache = async (type: "proxy" | "mirror" | "fixedPath" | "all") => { + const handleClearCache = async (type: "proxy" | "mirror" | "all") => { try { const token = localStorage.getItem("token") if (!token) { @@ -253,7 +251,7 @@ export default function CachePage() { } } - const renderCacheConfig = (type: "proxy" | "mirror" | "fixedPath") => { + const renderCacheConfig = (type: "proxy" | "mirror" ) => { if (!configs) return null const config = configs[type] @@ -425,55 +423,6 @@ export default function CachePage() { {renderCacheConfig("mirror")} - - {/* 固定路径缓存 */} - - - 固定路径缓存 -
- handleToggleCache("fixedPath", checked)} - /> - -
-
- -
-
-
缓存项数量
-
{stats?.fixedPath.total_items ?? 0}
-
-
-
总大小
-
{formatBytes(stats?.fixedPath.total_size ?? 0)}
-
-
-
命中次数
-
{stats?.fixedPath.hit_count ?? 0}
-
-
-
未命中次数
-
{stats?.fixedPath.miss_count ?? 0}
-
-
-
命中率
-
{(stats?.fixedPath.hit_rate ?? 0).toFixed(2)}%
-
-
-
节省带宽
-
{formatBytes(stats?.fixedPath.bytes_saved ?? 0)}
-
-
- {renderCacheConfig("fixedPath")} -
-
) diff --git a/web/app/dashboard/config/page.tsx b/web/app/dashboard/config/page.tsx index 82b865e..c0568e4 100644 --- a/web/app/dashboard/config/page.tsx +++ b/web/app/dashboard/config/page.tsx @@ -44,12 +44,6 @@ interface PathMapping { MaxSize?: number // 最大文件大小阈值 } -interface FixedPath { - Path: string - TargetHost: string - TargetURL: string -} - interface CompressionConfig { Enabled: boolean Level: number @@ -61,7 +55,6 @@ interface Config { Gzip: CompressionConfig Brotli: CompressionConfig } - FixedPaths: FixedPath[] } export default function ConfigPage() { @@ -85,13 +78,7 @@ export default function ConfigPage() { sizeThresholdUnit: 'MB' as 'B' | 'KB' | 'MB' | 'GB', maxSizeUnit: 'MB' as 'B' | 'KB' | 'MB' | 'GB', }) - const [fixedPathDialogOpen, setFixedPathDialogOpen] = useState(false) - const [editingFixedPath, setEditingFixedPath] = useState(null) - const [newFixedPath, setNewFixedPath] = useState({ - Path: "", - TargetHost: "", - TargetURL: "", - }) + const [extensionMapDialogOpen, setExtensionMapDialogOpen] = useState(false) const [editingPath, setEditingPath] = useState(null) const [editingExtension, setEditingExtension] = useState<{ext: string, target: string} | null>(null) @@ -107,7 +94,6 @@ export default function ConfigPage() { } | null>(null); const [deletingPath, setDeletingPath] = useState(null) - const [deletingFixedPath, setDeletingFixedPath] = useState(null) const [deletingExtension, setDeletingExtension] = useState<{path: string, ext: string} | null>(null) const fetchConfig = useCallback(async () => { @@ -231,20 +217,6 @@ export default function ConfigPage() { }) }, [handleDialogOpenChange]) - const handleFixedPathDialogOpenChange = useCallback((open: boolean) => { - handleDialogOpenChange(open, (isOpen) => { - setFixedPathDialogOpen(isOpen) - if (!isOpen) { - setEditingFixedPath(null) - setNewFixedPath({ - Path: "", - TargetHost: "", - TargetURL: "", - }) - } - }) - }, [handleDialogOpenChange]) - const handleExtensionMapDialogOpenChange = useCallback((open: boolean) => { handleDialogOpenChange(open, (isOpen) => { setExtensionMapDialogOpen(isOpen) @@ -453,95 +425,8 @@ export default function ConfigPage() { }) } - const addFixedPath = () => { - if (!config) return - const { Path, TargetHost, TargetURL } = newFixedPath - - // 验证输入 - if (!Path.trim() || !TargetHost.trim() || !TargetURL.trim()) { - toast({ - title: "错误", - description: "所有字段都不能为空", - variant: "destructive", - }) - return - } - // 验证路径格式 - if (!Path.startsWith('/')) { - toast({ - title: "错误", - description: "路径必须以/开头", - variant: "destructive", - }) - return - } - // 验证URL格式 - try { - new URL(TargetURL) - } catch { - toast({ - title: "错误", - description: "目标URL格式不正确", - variant: "destructive", - }) - return - } - - // 验证主机名格式 - if (!/^[a-zA-Z0-9][a-zA-Z0-9-_.]+[a-zA-Z0-9]$/.test(TargetHost)) { - toast({ - title: "错误", - description: "目标主机格式不正确", - variant: "destructive", - }) - return - } - - const newConfig = { ...config } - if (editingFixedPath) { - const index = newConfig.FixedPaths.findIndex(p => p.Path === editingFixedPath.Path) - if (index !== -1) { - newConfig.FixedPaths[index] = newFixedPath - } - } else { - // 检查路径是否已存在 - if (newConfig.FixedPaths.some(p => p.Path === Path)) { - toast({ - title: "错误", - description: "该路径已存在", - variant: "destructive", - }) - return - } - newConfig.FixedPaths.push(newFixedPath) - } - - setConfig(newConfig) - setFixedPathDialogOpen(false) - setEditingFixedPath(null) - setNewFixedPath({ - Path: "", - TargetHost: "", - TargetURL: "", - }) - - toast({ - title: "成功", - description: "固定路径已更新", - }) - } - - const editFixedPath = (path: FixedPath) => { - setEditingFixedPath(path) - setNewFixedPath({ - Path: path.Path, - TargetHost: path.TargetHost, - TargetURL: path.TargetURL, - }) - setFixedPathDialogOpen(true) - } const openAddPathDialog = () => { setEditingPathData(null) @@ -557,32 +442,6 @@ export default function ConfigPage() { setPathDialogOpen(true) } - const openAddFixedPathDialog = () => { - setEditingFixedPath(null) - setNewFixedPath({ - Path: "", - TargetHost: "", - TargetURL: "", - }) - setFixedPathDialogOpen(true) - } - - const deleteFixedPath = (path: FixedPath) => { - setDeletingFixedPath(path) - } - - const confirmDeleteFixedPath = () => { - if (!config || !deletingFixedPath) return - const newConfig = { ...config } - newConfig.FixedPaths = newConfig.FixedPaths.filter(p => p.Path !== deletingFixedPath.Path) - setConfig(newConfig) - setDeletingFixedPath(null) - toast({ - title: "成功", - description: "固定路径已删除", - }) - } - const exportConfig = () => { if (!config) return const blob = new Blob([JSON.stringify(config, null, 2)], { type: 'application/json' }) @@ -618,10 +477,6 @@ export default function ConfigPage() { throw new Error('配置文件压缩设置格式不正确') } - if (!Array.isArray(newConfig.FixedPaths)) { - throw new Error('配置文件固定路径格式不正确') - } - // 验证路径映射 for (const [path, target] of Object.entries(newConfig.MAP)) { if (!path.startsWith('/')) { @@ -1059,92 +914,6 @@ export default function ConfigPage() { - - -
- -
- - - - - 路径 - 目标主机 - 目标 URL - 操作 - - - - {config?.FixedPaths.map((path, index) => ( - - {path.Path} - {path.TargetHost} - {path.TargetURL} - -
- - -
-
-
- ))} -
-
- - - - - - {editingFixedPath ? "编辑固定路径" : "添加固定路径"} - - -
-
- - setNewFixedPath({ ...newFixedPath, Path: e.target.value })} - placeholder="/example" - /> -
-
- - setNewFixedPath({ ...newFixedPath, TargetHost: e.target.value })} - placeholder="example.com" - /> -
-
- - setNewFixedPath({ ...newFixedPath, TargetURL: e.target.value })} - placeholder="https://example.com" - /> -
- -
-
-
-
@@ -1203,25 +972,7 @@ export default function ConfigPage() { - - handleDeleteDialogOpenChange(open, setDeletingFixedPath)} - > - - - 确认删除 - - 确定要删除固定路径 “{deletingFixedPath?.Path}” 吗?此操作无法撤销。 - - - - 取消 - 删除 - - - - + handleDeleteDialogOpenChange(open, setDeletingExtension)}