package main
import (
"encoding/json"
"fmt"
"html/template"
"log"
"net/http"
"strconv"
"github.com/darkit/goproxy/examples/rewriter/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}}
{{$i}} |
{{$rule.Pattern}} |
{{$rule.Replacement}} |
{{if $rule.UseRegex}}正则表达式{{else}}前缀匹配{{end}} |
{{$rule.Description}} |
{{if $rule.Enabled}}启用{{else}}禁用{{end}}
|
{{if $rule.Enabled}}
{{else}}
{{end}}
|
{{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))
}