package main
import (
"context"
"encoding/json"
"fmt"
"html/template"
"log"
"net/http"
"runtime"
"strconv"
"strings"
"github.com/darkit/goproxy/examples/plugin"
)
// 全局插件管理器
var pm *plugin.PluginManager
// AdminHandler 处理管理界面主页
func AdminHandler(w http.ResponseWriter, r *http.Request) {
// HTML模板
tmpl := `
插件管理系统
插件管理系统
系统信息
操作系统: {{.OS}}
动态加载支持: {{if .DynamicLoadingSupported}}是{{else}}否{{end}}
插件目录: {{.PluginsDir}}
已加载插件数量: {{len .Plugins}}
已安装插件
{{range .Plugins}}
{{.Description}}
{{if .Config}}
配置:
{{range $key, $value := .Config}}
{{end}}
{{end}}
{{if .Enabled}}
{{else}}
{{end}}
{{end}}
{{if not .Plugins}}
没有已安装的插件。
{{end}}
操作
`
// 解析模板
t, err := template.New("admin").Parse(tmpl)
if err != nil {
http.Error(w, fmt.Sprintf("模板解析错误: %v", err), http.StatusInternalServerError)
return
}
// 准备数据
data := struct {
Plugins []plugin.PluginInfo
OS string
DynamicLoadingSupported bool
PluginsDir string
}{
Plugins: pm.GetPluginInfos(),
OS: strings.Title(strings.ToLower(fmt.Sprintf("%s", strings.Split(runtime.GOOS, "/")[0]))),
DynamicLoadingSupported: pm.IsDynamicLoadingSupported(),
PluginsDir: pluginsDir,
}
// 渲染模板
if err := t.Execute(w, data); err != nil {
http.Error(w, fmt.Sprintf("模板渲染错误: %v", err), http.StatusInternalServerError)
}
}
// EnablePluginHandler 启用插件
func EnablePluginHandler(w http.ResponseWriter, r *http.Request) {
pluginName := r.URL.Path[len("/enable/"):]
if err := pm.EnablePlugin(pluginName); err != nil {
http.Error(w, fmt.Sprintf("启用插件失败: %v", err), http.StatusInternalServerError)
return
}
// 尝试初始化和启动插件
ctx := context.Background()
plugin, exists := pm.GetPlugin(pluginName)
if exists && plugin.IsEnabled() {
config, _ := pm.GetPluginConfig(pluginName)
if err := plugin.Init(ctx, config); err != nil {
http.Error(w, fmt.Sprintf("初始化插件失败: %v", err), http.StatusInternalServerError)
return
}
if err := plugin.Start(ctx); err != nil {
http.Error(w, fmt.Sprintf("启动插件失败: %v", err), http.StatusInternalServerError)
return
}
}
http.Redirect(w, r, "/", http.StatusSeeOther)
}
// DisablePluginHandler 禁用插件
func DisablePluginHandler(w http.ResponseWriter, r *http.Request) {
pluginName := r.URL.Path[len("/disable/"):]
// 先停止插件
ctx := context.Background()
plugin, exists := pm.GetPlugin(pluginName)
if exists && plugin.IsEnabled() {
if err := plugin.Stop(ctx); err != nil {
http.Error(w, fmt.Sprintf("停止插件失败: %v", err), http.StatusInternalServerError)
return
}
}
// 禁用插件
if err := pm.DisablePlugin(pluginName); err != nil {
http.Error(w, fmt.Sprintf("禁用插件失败: %v", err), http.StatusInternalServerError)
return
}
http.Redirect(w, r, "/", http.StatusSeeOther)
}
// ConfigPluginHandler 配置插件
func ConfigPluginHandler(w http.ResponseWriter, r *http.Request) {
pluginName := r.URL.Path[len("/config/"):]
if r.Method == http.MethodPost {
// 处理配置表单提交
if err := r.ParseForm(); err != nil {
http.Error(w, fmt.Sprintf("解析表单失败: %v", err), http.StatusBadRequest)
return
}
// 收集配置项
config := make(map[string]interface{})
for key, values := range r.PostForm {
if key == "pluginName" {
continue // 跳过插件名称字段
}
if len(values) > 0 {
// 尝试将值转换为适当的类型
value := values[0]
// 布尔值处理
if value == "true" {
config[key] = true
} else if value == "false" {
config[key] = false
} else if strings.Contains(value, ".") {
// 尝试解析为浮点数
if f, err := strconv.ParseFloat(value, 64); err == nil {
config[key] = f
} else {
config[key] = value
}
} else if i, err := strconv.Atoi(value); err == nil {
// 尝试解析为整数
config[key] = i
} else {
// 默认为字符串
config[key] = value
}
}
}
// 保存配置
if err := pm.SetPluginConfig(pluginName, config); err != nil {
http.Error(w, fmt.Sprintf("保存配置失败: %v", err), http.StatusInternalServerError)
return
}
// 重定向回主页
http.Redirect(w, r, "/", http.StatusSeeOther)
return
}
// 获取插件信息和配置
info, config := getPluginInfo(pluginName)
if info == nil {
http.Error(w, "插件不存在", http.StatusNotFound)
return
}
// 配置表单模板
tmpl := `
配置 {{.Info.Name}}
配置 {{.Info.Name}}
返回插件列表
`
// 解析模板
t, err := template.New("config").Parse(tmpl)
if err != nil {
http.Error(w, fmt.Sprintf("模板解析错误: %v", err), http.StatusInternalServerError)
return
}
// 准备数据
data := struct {
Info *plugin.PluginInfo
Config map[string]interface{}
}{
Info: info,
Config: config,
}
// 渲染模板
if err := t.Execute(w, data); err != nil {
http.Error(w, fmt.Sprintf("模板渲染错误: %v", err), http.StatusInternalServerError)
}
}
// ReloadPluginsHandler 重新加载插件
func ReloadPluginsHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Redirect(w, r, "/", http.StatusSeeOther)
return
}
// 停止所有插件
ctx := context.Background()
if err := pm.StopPlugins(ctx); err != nil {
http.Error(w, fmt.Sprintf("停止插件失败: %v", err), http.StatusInternalServerError)
return
}
// 重新加载插件
if err := pm.LoadPlugins(); err != nil {
http.Error(w, fmt.Sprintf("加载插件失败: %v", err), http.StatusInternalServerError)
return
}
// 初始化和启动插件
if err := pm.InitPlugins(ctx); err != nil {
http.Error(w, fmt.Sprintf("初始化插件失败: %v", err), http.StatusInternalServerError)
return
}
if err := pm.StartPlugins(ctx); err != nil {
http.Error(w, fmt.Sprintf("启动插件失败: %v", err), http.StatusInternalServerError)
return
}
http.Redirect(w, r, "/", http.StatusSeeOther)
}
// API接口处理器 - 返回插件列表
func APIPluginsHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
plugins := pm.GetPluginInfos()
if err := json.NewEncoder(w).Encode(plugins); err != nil {
http.Error(w, fmt.Sprintf("编码JSON失败: %v", err), http.StatusInternalServerError)
}
}
// getPluginInfo 获取插件信息和配置
func getPluginInfo(name string) (*plugin.PluginInfo, map[string]interface{}) {
plugins := pm.GetPluginInfos()
for _, info := range plugins {
if info.Name == name {
config, _ := pm.GetPluginConfig(name)
return &info, config
}
}
return nil, nil
}
// 插件目录
var pluginsDir = "./plugins"
func main3() {
// 创建插件管理器
pm = plugin.NewPluginManager(pluginsDir)
// 加载插件
if err := pm.LoadPlugins(); err != nil {
log.Fatalf("加载插件失败: %v", err)
}
// 初始化并启动插件
ctx := context.Background()
if err := pm.InitPlugins(ctx); err != nil {
log.Printf("初始化插件失败: %v", err)
}
if err := pm.StartPlugins(ctx); err != nil {
log.Printf("启动插件失败: %v", err)
}
// 注册处理器
http.HandleFunc("/", AdminHandler)
http.HandleFunc("/enable/", EnablePluginHandler)
http.HandleFunc("/disable/", DisablePluginHandler)
http.HandleFunc("/config/", ConfigPluginHandler)
http.HandleFunc("/reload", ReloadPluginsHandler)
http.HandleFunc("/api/plugins", APIPluginsHandler)
// 启动Web服务器
log.Println("管理界面启动在 :8080...")
log.Fatal(http.ListenAndServe(":8080", nil))
}