This commit is contained in:
wjqserver 2025-06-20 16:33:27 +08:00
commit b10790c212
40 changed files with 4149 additions and 0 deletions

152
gen/init.go Normal file
View file

@ -0,0 +1,152 @@
package gen
import (
"caddydash/config"
"caddydash/db"
"fmt"
"os"
"path/filepath"
"time"
)
// 把指定目录下的文件作为模板读入
func ReadTmplToDB(dir string, cdb *db.ConfigDB) error {
// 遍历目录下的所有文件
files, err := os.ReadDir(dir)
if err != nil {
return err
}
for _, file := range files {
if file.IsDir() {
continue
}
// 读取文件内容
content, err := os.ReadFile(filepath.Join(dir, file.Name()))
if err != nil {
return err
}
tmplEntry := db.TemplateEntry{
Filename: file.Name(),
TemplateType: file.Name(),
Content: content,
UpdatedAt: time.Now().Unix(),
}
// 存储到数据库
err = cdb.SaveTemplate(tmplEntry)
if err != nil {
return err
}
// 输出tmpl名
fmt.Printf("Read template: %s\n", file.Name())
}
return nil
}
func Add80SiteConfig(cfg *config.Config, cdb *db.ConfigDB) error {
// 检查:80是否已存在于数据库中
_, err := cdb.GetParams(":80")
if err == nil {
// 如果存在,则不添加
return nil
}
siteConfig := CaddyUniConfig{
DomainConfig: CaddyUniDomainConfig{
Domain: ":80",
MutiDomains: false,
Domains: []string{":80"},
},
Mode: "uni",
FileServer: CaddyUniFileServerConfig{
EnableFileServer: true,
FileDirPath: cfg.Server.CaddyDir + "pages/demo",
EnableBrowser: false,
},
Log: CaddyUniLogConfig{
EnableLog: true,
LogDomain: ":80",
},
ErrorPage: CaddyUniErrorPageConfig{
EnableErrorPage: true,
},
Encode: CaddyUniEncodeConfig{
EnableEncode: true,
},
}
// 制作db.ParamsEntry
gobData, err := EncodeGobConfig(siteConfig)
if err != nil {
return err
}
/*
originConfig := db.CaddyfileConfig{
Domain: ":80",
TmplType: "file_server",
FileServer: db.FileServerConfig{
FileDirPath: cfg.Server.CaddyDir + "pages/demo",
EnableBrowser: false,
},
Log: db.LogConfig{
EnableLog: true,
LogDomain: ":80",
},
ErrorPage: db.ErrorPageConfig{
EnableErrorPage: true,
},
Encode: db.EncodeConfig{
EnableEncode: true,
},
}
*/
originGobData, err := EncodeGobConfig(siteConfig)
if err != nil {
return err
}
paramsEntry := db.ParamsEntry{
Filename: ":80",
TemplateType: "file_server",
ParamsGOB: gobData,
ParamsOrigin: originGobData,
CreatedAt: time.Now().Unix(),
UpdatedAt: time.Now().Unix(),
}
filename := paramsEntry.Filename
// 保存到数据库
err = cdb.SaveParams(paramsEntry)
if err != nil {
return err
}
// 渲染配置
err = RenderConfig(filename, cdb)
if err != nil {
err = fmt.Errorf("render config error: %w", err)
return err
}
// 写入文件
renderedEntry, err := cdb.GetRenderedConfig(filename)
if err != nil {
err = fmt.Errorf("get rendered config error: %w", err)
return err
}
err = os.WriteFile(cfg.Server.CaddyDir+"config.d/"+filename, renderedEntry.RenderedContent, 0644)
if err != nil {
err = fmt.Errorf("write rendered config file error: %w", err)
return err
}
return nil
}

150
gen/render.go Normal file
View file

@ -0,0 +1,150 @@
package gen
import (
"bytes"
"caddydash/db"
"encoding/gob"
"fmt"
"text/template"
)
func RenderConfig(site string, cdb *db.ConfigDB) error {
// 检索site config
paramsEntry, err := cdb.GetParams(site)
if err != nil {
return err
}
var caddycfg CaddyUniConfig
err = DecodeGobConfig(paramsEntry.ParamsGOB, &caddycfg)
if err != nil {
return err
}
// 读取模板
//tmplEntry, err := cdb.GetTemplate("reverse_proxy")
tmplEntry, err := cdb.GetTemplate(caddycfg.Mode)
if err != nil {
return err
}
rpTmpl := string(tmplEntry.Content)
// 使用caddycfg渲染最终产物
parsedTmpl, parseErr := template.New(tmplEntry.Filename).Parse(rpTmpl)
if parseErr != nil {
return fmt.Errorf("db: failed to parse template content for '%s': %w", tmplEntry.Filename, parseErr)
}
var renderedContentBuilder bytes.Buffer
if err := parsedTmpl.Execute(&renderedContentBuilder, caddycfg); err != nil {
return fmt.Errorf("db: failed to render template '%s': %w", tmplEntry.Filename, err)
}
// 保存渲染结果
renderedEntry := db.RenderedConfigEntry{
Filename: caddycfg.DomainConfig.Domain, // 使用域名作为文件名
RenderedContent: renderedContentBuilder.Bytes(),
}
// 保存渲染产物
if err := cdb.SaveRenderedConfig(renderedEntry); err != nil {
return fmt.Errorf("db: failed to save rendered config for '%s': %w", caddycfg.DomainConfig.Domain, err)
}
return nil
}
// 把caddycfg内容转为GOB
func EncodeGobConfig(caddycfg any) ([]byte, error) {
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
if err := enc.Encode(caddycfg); err != nil {
return nil, fmt.Errorf("db: failed to Encode struct to GOB: %w", err)
}
return buf.Bytes(), nil // 返回编码后的字节切片.
}
func DecodeGobConfig(data []byte, tmplStruct any) error {
buf := bytes.NewBuffer(data)
dec := gob.NewDecoder(buf)
if err := dec.Decode(tmplStruct); err != nil {
return fmt.Errorf("db: failed to Decode GOB to struct: %w", err)
}
return nil
}
/*
func RenderConfig(site string, cdb *db.ConfigDB) error {
// 检索site config
paramsEntry, err := cdb.GetParams(site)
if err != nil {
return err
}
var caddycfg any
var specificConfigType interface{}
if paramsEntry.TemplateType == "reverse_proxy" {
specificConfigType = &CaddyReverseProxyConfig{}
} else if paramsEntry.TemplateType == "file_server" {
specificConfigType = &CaddyFileServerConfig{}
} else {
return fmt.Errorf("unknown template type: %s", paramsEntry.TemplateType)
}
err = DecodeGobConfig(paramsEntry.ParamsGOB, specificConfigType)
if err != nil {
log.Printf("decode gob config error: %v", err)
return err
}
caddycfg = specificConfigType
// 读取模板
//tmplEntry, err := cdb.GetTemplate("reverse_proxy")
tmplEntry, err := cdb.GetTemplate(paramsEntry.TemplateType)
if err != nil {
log.Printf("get template error: %v", err)
tmplList, err := cdb.RangeTemplates()
if err != nil {
return err
}
log.Printf("template list: %v, GetName %s", tmplList, paramsEntry.TemplateType)
return err
}
rpTmpl := string(tmplEntry.Content)
// 使用caddycfg渲染最终产物
parsedTmpl, parseErr := template.New(tmplEntry.Filename).Parse(rpTmpl)
if parseErr != nil {
return fmt.Errorf("db: failed to parse template content for '%s': %w", tmplEntry.Filename, parseErr)
}
var renderedContentBuilder bytes.Buffer
if err := parsedTmpl.Execute(&renderedContentBuilder, caddycfg); err != nil {
return fmt.Errorf("db: failed to render template '%s': %w", tmplEntry.Filename, err)
}
// 类型断言获得domain
var domain string
switch cfg := caddycfg.(type) {
case *CaddyReverseProxyConfig:
domain = cfg.Domain
case *CaddyFileServerConfig:
domain = cfg.Domain
default:
return fmt.Errorf("unknown config type for domain extraction")
}
// 保存渲染结果
renderedEntry := db.RenderedConfigEntry{
Filename: domain, // 使用域名作为文件名
RenderedContent: renderedContentBuilder.Bytes(),
}
// 保存渲染产物
if err := cdb.SaveRenderedConfig(renderedEntry); err != nil {
return fmt.Errorf("db: failed to save rendered config for '%s': %w", domain, err)
}
return nil
}
*/

79
gen/struct.go Normal file
View file

@ -0,0 +1,79 @@
package gen
/*
type CaddyReverseProxyConfig struct {
Domain string // 域名; 例如 example.com
ReverseProxy string // 反向代理目标; 例如 127.0.0.1:8080 (这里简化为单个目标)
Headers []string // 自定义响应Header
HeadersUp []string // 自定义请求头列表; 例如 ["XXX0 XX", "XXX1 XXX"]
EnableLog bool // 是否导入 log 指令
LogDomain string // log 指令的域名参数
EnableErrorPage bool // 是否导入 error_page 指令
EnableEncode bool // 是否导入 encode 指令
}
type CaddyFileServerConfig struct {
Domain string // 域名; 例如 example.com
FileDirPath string // 文件目录
EnableBrowser bool // 是否导入 browse 指令
Headers []string //
EnableLog bool // 是否导入 log 指令
LogDomain string // log 指令的域名参数
EnableErrorPage bool // 是否导入 error_page 指令
EnableEncode bool // 是否导入 encode 指令
}
*/
func HeadersMapToHeadersUp(headers map[string][]string) []string {
var headersUp []string
for key, values := range headers {
for _, value := range values {
headersUp = append(headersUp, key+" "+value)
}
}
return headersUp
}
type CaddyUniConfig struct {
DomainConfig CaddyUniDomainConfig `json:"domain_config"`
Mode string `json:"mode"`
Upstream CaddyUniUpstreamConfig `json:"upstream_config"`
FileServer CaddyUniFileServerConfig `json:"file_server_config"`
Headers map[string][]string `json:"headers"`
Log CaddyUniLogConfig `json:"log_config"`
ErrorPage CaddyUniErrorPageConfig `json:"error_page_config"`
Encode CaddyUniEncodeConfig `json:"encode_config"`
}
type CaddyUniDomainConfig struct {
Domain string `json:"domain"`
MutiDomains bool `json:"muti_domains"`
Domains []string `json:"domains"`
}
type CaddyUniUpstreamConfig struct {
EnableUpStream bool `json:"enable_upstream"`
UpStream string `json:"upstream"`
MutiUpStreams bool `json:"muti_upstream"`
UpStreams []string `json:"upstream_servers"`
UpStreamHeaders map[string][]string `json:"upstream_headers"`
}
type CaddyUniFileServerConfig struct {
EnableFileServer bool `json:"enable_file_server"`
FileDirPath string `json:"file_dir_path"`
EnableBrowser bool `json:"enable_browser"`
}
type CaddyUniLogConfig struct {
EnableLog bool `json:"enable_log"`
LogDomain string `json:"log_domain"`
}
type CaddyUniErrorPageConfig struct {
EnableErrorPage bool `json:"enable_error_page"`
}
type CaddyUniEncodeConfig struct {
EnableEncode bool `json:"enable_encode"`
}