package main import ( "encoding/json" "fmt" "html/template" "log" "net/http" "strconv" "github.com/darkit/goproxy/pkg/rewriter" ) // 全局重写器实例 var rw *rewriter.Rewriter // 规则配置文件路径 var rulesFile = "rules.json" // AdminHandler Web管理页面处理器 func AdminHandler(w http.ResponseWriter, r *http.Request) { // 定义模板 tmpl := ` URL重写规则管理

URL重写规则管理

当前规则

{{range $i, $rule := .Rules}} {{end}}
索引 匹配模式 替换模式 类型 描述 状态 操作
{{$i}} {{$rule.Pattern}} {{$rule.Replacement}} {{if $rule.UseRegex}}正则表达式{{else}}前缀匹配{{end}} {{$rule.Description}} {{if $rule.Enabled}}启用{{else}}禁用{{end}} {{if $rule.Enabled}} {{else}} {{end}}

添加新规则

保存配置

` // 解析模板 t, err := template.New("admin").Parse(tmpl) if err != nil { http.Error(w, fmt.Sprintf("模板解析错误: %v", err), http.StatusInternalServerError) return } // 渲染模板 data := struct { Rules []*rewriter.RewriteRule }{ Rules: rw.GetRules(), } if err := t.Execute(w, data); err != nil { http.Error(w, fmt.Sprintf("模板渲染错误: %v", err), http.StatusInternalServerError) } } // AddRuleHandler 添加规则处理器 func AddRuleHandler(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Redirect(w, r, "/", http.StatusSeeOther) return } r.ParseForm() pattern := r.Form.Get("pattern") replacement := r.Form.Get("replacement") useRegex := r.Form.Get("regex") == "on" description := r.Form.Get("description") if pattern == "" || replacement == "" { http.Error(w, "匹配模式和替换模式不能为空", http.StatusBadRequest) return } if err := rw.AddRuleWithDescription(pattern, replacement, useRegex, description); err != nil { http.Error(w, fmt.Sprintf("添加规则失败: %v", err), http.StatusInternalServerError) return } http.Redirect(w, r, "/", http.StatusSeeOther) } // EnableRuleHandler 启用规则处理器 func EnableRuleHandler(w http.ResponseWriter, r *http.Request) { // 解析URL中的规则索引 indexStr := r.URL.Path[len("/enable/"):] index, err := strconv.Atoi(indexStr) if err != nil { http.Error(w, "无效的规则索引", http.StatusBadRequest) return } if err := rw.EnableRule(index); err != nil { http.Error(w, fmt.Sprintf("启用规则失败: %v", err), http.StatusInternalServerError) return } http.Redirect(w, r, "/", http.StatusSeeOther) } // DisableRuleHandler 禁用规则处理器 func DisableRuleHandler(w http.ResponseWriter, r *http.Request) { // 解析URL中的规则索引 indexStr := r.URL.Path[len("/disable/"):] index, err := strconv.Atoi(indexStr) if err != nil { http.Error(w, "无效的规则索引", http.StatusBadRequest) return } if err := rw.DisableRule(index); err != nil { http.Error(w, fmt.Sprintf("禁用规则失败: %v", err), http.StatusInternalServerError) return } http.Redirect(w, r, "/", http.StatusSeeOther) } // RemoveRuleHandler 删除规则处理器 func RemoveRuleHandler(w http.ResponseWriter, r *http.Request) { // 解析URL中的规则索引 indexStr := r.URL.Path[len("/remove/"):] index, err := strconv.Atoi(indexStr) if err != nil { http.Error(w, "无效的规则索引", http.StatusBadRequest) return } if err := rw.RemoveRule(index); err != nil { http.Error(w, fmt.Sprintf("删除规则失败: %v", err), http.StatusInternalServerError) return } http.Redirect(w, r, "/", http.StatusSeeOther) } // SaveRulesHandler 保存规则处理器 func SaveRulesHandler(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Redirect(w, r, "/", http.StatusSeeOther) return } if err := rw.SaveRulesToFile(rulesFile); err != nil { http.Error(w, fmt.Sprintf("保存规则失败: %v", err), http.StatusInternalServerError) return } http.Redirect(w, r, "/", http.StatusSeeOther) } // APIHandler API处理器,返回JSON格式的规则列表 func APIHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") rules := rw.GetRules() json.NewEncoder(w).Encode(rules) } func main() { // 创建重写器 rw = rewriter.NewRewriter() // 尝试从文件加载规则 if err := rw.LoadRulesFromFile(rulesFile); err != nil { log.Printf("加载规则失败: %v, 将使用空规则集", err) } // 注册处理器 http.HandleFunc("/", AdminHandler) http.HandleFunc("/add", AddRuleHandler) http.HandleFunc("/enable/", EnableRuleHandler) http.HandleFunc("/disable/", DisableRuleHandler) http.HandleFunc("/remove/", RemoveRuleHandler) http.HandleFunc("/save", SaveRulesHandler) http.HandleFunc("/api/rules", APIHandler) // 启动服务器 log.Println("管理界面启动在 :8080...") log.Fatal(http.ListenAndServe(":8080", nil)) }