612d68f56f
Go + Vue 管理台,SQLite 持久化;支持隧道/域名穿透、域名转发插件链、访客认证、 IP 规则、API Key、Docker 单镜像部署;配置通过 Web 系统设置管理,无需 YAML 文件。 Co-authored-by: Cursor <cursoragent@cursor.com>
88 lines
1.9 KiB
Go
88 lines
1.9 KiB
Go
package forwardplugin
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
func ValidateAndNormalizePlugins(entries []PluginEntry) ([]PluginEntry, error) {
|
|
if len(entries) == 0 {
|
|
return nil, nil
|
|
}
|
|
out := make([]PluginEntry, 0, len(entries))
|
|
for i, e := range entries {
|
|
typ := strings.TrimSpace(e.Type)
|
|
if typ == "" {
|
|
return nil, fmt.Errorf("plugins[%d].type 不能为空", i)
|
|
}
|
|
factory, ok := getFactory(typ)
|
|
if !ok {
|
|
return nil, fmt.Errorf("未知插件类型: %s", typ)
|
|
}
|
|
cfg := e.Config
|
|
if len(cfg) == 0 {
|
|
cfg = json.RawMessage("{}")
|
|
}
|
|
p, err := factory(cfg)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("plugins[%d]: %w", i, err)
|
|
}
|
|
if err := p.ValidateConfig(cfg); err != nil {
|
|
return nil, fmt.Errorf("plugins[%d]: %w", i, err)
|
|
}
|
|
normalized, err := normalizeConfig(cfg, p)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("plugins[%d]: %w", i, err)
|
|
}
|
|
out = append(out, PluginEntry{
|
|
Type: typ,
|
|
Enabled: e.Enabled,
|
|
Config: normalized,
|
|
})
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func normalizeConfig(raw json.RawMessage, p Plugin) (json.RawMessage, error) {
|
|
if norm, ok := p.(ConfigNormalizer); ok {
|
|
return norm.NormalizeConfig(raw)
|
|
}
|
|
return raw, nil
|
|
}
|
|
|
|
type ConfigNormalizer interface {
|
|
NormalizeConfig(raw json.RawMessage) (json.RawMessage, error)
|
|
}
|
|
|
|
func BuildChain(entries []PluginEntry) (*Chain, error) {
|
|
plugins := make([]Plugin, 0, len(entries))
|
|
for _, e := range entries {
|
|
if !e.Enabled {
|
|
continue
|
|
}
|
|
factory, ok := getFactory(e.Type)
|
|
if !ok {
|
|
return nil, fmt.Errorf("未知插件类型: %s", e.Type)
|
|
}
|
|
cfg := e.Config
|
|
if len(cfg) == 0 {
|
|
cfg = json.RawMessage("{}")
|
|
}
|
|
p, err := factory(cfg)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
plugins = append(plugins, p)
|
|
}
|
|
return &Chain{plugins: plugins}, nil
|
|
}
|
|
|
|
func PluginsJSON(entries []PluginEntry) string {
|
|
if len(entries) == 0 {
|
|
return "[]"
|
|
}
|
|
b, _ := json.Marshal(entries)
|
|
return string(b)
|
|
}
|