SDK下载乱码问题修复

This commit is contained in:
robin
2026-03-04 19:44:21 +08:00
parent 30a1b4fa5e
commit c040d7c90d
6 changed files with 179 additions and 5 deletions

View File

@@ -1,6 +1,7 @@
package apps package apps
import ( import (
"net/url"
"os" "os"
"path/filepath" "path/filepath"
@@ -49,6 +50,6 @@ func (this *SdkDocAction) RunGet(params struct {
} }
this.AddHeader("Content-Type", "text/markdown; charset=utf-8") this.AddHeader("Content-Type", "text/markdown; charset=utf-8")
this.AddHeader("Content-Disposition", "attachment; filename=\""+downloadName+"\";") this.AddHeader("Content-Disposition", "attachment; filename=\"sdk-doc.md\"; filename*=UTF-8''"+url.PathEscape(downloadName))
_, _ = this.ResponseWriter.Write(data) _, _ = this.ResponseWriter.Write(data)
} }

View File

@@ -2,6 +2,7 @@ package apps
import ( import (
"io" "io"
"net/url"
"os" "os"
"path/filepath" "path/filepath"
@@ -58,7 +59,7 @@ func (this *SdkDownloadAction) RunGet(params struct {
this.AddHeader("X-SDK-Filename", downloadName) this.AddHeader("X-SDK-Filename", downloadName)
} else { } else {
this.AddHeader("Content-Type", "application/zip") this.AddHeader("Content-Type", "application/zip")
this.AddHeader("Content-Disposition", "attachment; filename=\""+downloadName+"\";") this.AddHeader("Content-Disposition", "attachment; filename=\"sdk-download\"; filename*=UTF-8''"+url.PathEscape(downloadName))
} }
this.AddHeader("X-Accel-Buffering", "no") this.AddHeader("X-Accel-Buffering", "no")
_, _ = io.Copy(this.ResponseWriter, fp) _, _ = io.Copy(this.ResponseWriter, fp)

View File

@@ -1,5 +1,4 @@
*.zip *.zip
edge-dns edge-dns
configs/
logs/ logs/
data/ data/

View File

@@ -0,0 +1,171 @@
package configs
import (
"errors"
"os"
"path/filepath"
"github.com/iwind/TeaGo/Tea"
"gopkg.in/yaml.v3"
)
const ConfigFileName = "api_httpdns.yaml"
const oldConfigFileName = "api.yaml"
var sharedAPIConfig *APIConfig
type APIConfig struct {
OldRPC struct {
Endpoints []string `yaml:"endpoints"`
DisableUpdate bool `yaml:"disableUpdate"`
} `yaml:"rpc,omitempty"`
RPCEndpoints []string `yaml:"rpc.endpoints,flow" json:"rpc.endpoints"`
RPCDisableUpdate bool `yaml:"rpc.disableUpdate" json:"rpc.disableUpdate"`
NodeId string `yaml:"nodeId"`
Secret string `yaml:"secret"`
ListenAddr string `yaml:"listenAddr"`
HTTPSListenAddr string `yaml:"https.listenAddr" json:"https.listenAddr"`
HTTPSCert string `yaml:"https.cert" json:"https.cert"`
HTTPSKey string `yaml:"https.key" json:"https.key"`
LogDir string `yaml:"logDir" json:"logDir"`
}
func SharedAPIConfig() (*APIConfig, error) {
if sharedAPIConfig != nil {
return sharedAPIConfig, nil
}
config, err := LoadAPIConfig()
if err != nil {
return nil, err
}
sharedAPIConfig = config
return config, nil
}
func LoadAPIConfig() (*APIConfig, error) {
for _, filename := range []string{ConfigFileName, oldConfigFileName} {
var loadedData []byte
var loadedPath string
for _, candidate := range findConfigCandidates(filename) {
data, err := os.ReadFile(candidate)
if err != nil {
if os.IsNotExist(err) {
continue
}
return nil, err
}
loadedData = data
loadedPath = candidate
break
}
if len(loadedData) == 0 {
if filename == oldConfigFileName {
continue
}
return nil, errors.New("no config file '" + ConfigFileName + "' found")
}
config := &APIConfig{}
err := yaml.Unmarshal(loadedData, config)
if err != nil {
return nil, err
}
err = config.Init()
if err != nil {
return nil, err
}
if filename == oldConfigFileName {
config.OldRPC.Endpoints = nil
// 优先写回当前旧配置所在目录,避免依赖启动时工作目录
_ = config.WriteFile(filepath.Join(filepath.Dir(loadedPath), ConfigFileName))
}
return config, nil
}
return nil, errors.New("no config file '" + ConfigFileName + "' found")
}
func (c *APIConfig) Init() error {
if len(c.RPCEndpoints) == 0 && len(c.OldRPC.Endpoints) > 0 {
c.RPCEndpoints = c.OldRPC.Endpoints
c.RPCDisableUpdate = c.OldRPC.DisableUpdate
}
if len(c.RPCEndpoints) == 0 {
return errors.New("no valid 'rpc.endpoints'")
}
if len(c.NodeId) == 0 {
return errors.New("'nodeId' required")
}
if len(c.Secret) == 0 {
return errors.New("'secret' required")
}
// 兼容旧配置中的 listenAddr
if len(c.HTTPSListenAddr) == 0 {
if len(c.ListenAddr) > 0 {
c.HTTPSListenAddr = c.ListenAddr
} else {
c.HTTPSListenAddr = ":8443"
}
}
if len(c.HTTPSCert) == 0 {
// return errors.New("'https.cert' required")
}
if len(c.HTTPSKey) == 0 {
// return errors.New("'https.key' required")
}
return nil
}
func (c *APIConfig) WriteFile(path string) error {
data, err := yaml.Marshal(c)
if err != nil {
return err
}
return os.WriteFile(path, data, 0666)
}
func findConfigCandidates(filename string) []string {
candidates := []string{
Tea.ConfigFile(filename),
Tea.ConfigFile(filepath.Join("configs", filename)),
filename,
filepath.Join("configs", filename),
}
if exePath, err := os.Executable(); err == nil {
exeDir := filepath.Dir(exePath)
candidates = append(candidates,
filepath.Join(exeDir, filename),
filepath.Join(exeDir, "configs", filename),
filepath.Join(exeDir, "..", "configs", filename),
)
}
uniq := map[string]struct{}{}
result := make([]string, 0, len(candidates))
for _, candidate := range candidates {
candidate = filepath.Clean(candidate)
if len(candidate) == 0 {
continue
}
if _, ok := uniq[candidate]; ok {
continue
}
uniq[candidate] = struct{}{}
result = append(result, candidate)
}
return result
}

View File

@@ -1,6 +1,7 @@
package apps package apps
import ( import (
"net/url"
"os" "os"
"path/filepath" "path/filepath"
@@ -49,6 +50,6 @@ func (this *SdkDocAction) RunGet(params struct {
} }
this.AddHeader("Content-Type", "text/markdown; charset=utf-8") this.AddHeader("Content-Type", "text/markdown; charset=utf-8")
this.AddHeader("Content-Disposition", "attachment; filename=\""+downloadName+"\";") this.AddHeader("Content-Disposition", "attachment; filename=\"sdk-doc.md\"; filename*=UTF-8''"+url.PathEscape(downloadName))
_, _ = this.ResponseWriter.Write(data) _, _ = this.ResponseWriter.Write(data)
} }

View File

@@ -2,6 +2,7 @@ package apps
import ( import (
"io" "io"
"net/url"
"os" "os"
"path/filepath" "path/filepath"
@@ -58,7 +59,7 @@ func (this *SdkDownloadAction) RunGet(params struct {
this.AddHeader("X-SDK-Filename", downloadName) this.AddHeader("X-SDK-Filename", downloadName)
} else { } else {
this.AddHeader("Content-Type", "application/zip") this.AddHeader("Content-Type", "application/zip")
this.AddHeader("Content-Disposition", "attachment; filename=\""+downloadName+"\";") this.AddHeader("Content-Disposition", "attachment; filename=\"sdk-download\"; filename*=UTF-8''"+url.PathEscape(downloadName))
} }
this.AddHeader("X-Accel-Buffering", "no") this.AddHeader("X-Accel-Buffering", "no")
_, _ = io.Copy(this.ResponseWriter, fp) _, _ = io.Copy(this.ResponseWriter, fp)