SDK下载乱码问题修复
This commit is contained in:
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
1
EdgeHttpDNS/.gitignore
vendored
1
EdgeHttpDNS/.gitignore
vendored
@@ -1,5 +1,4 @@
|
|||||||
*.zip
|
*.zip
|
||||||
edge-dns
|
edge-dns
|
||||||
configs/
|
|
||||||
logs/
|
logs/
|
||||||
data/
|
data/
|
||||||
|
|||||||
171
EdgeHttpDNS/internal/configs/api_config.go
Normal file
171
EdgeHttpDNS/internal/configs/api_config.go
Normal 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
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user