mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-03 04:50:52 +08:00
fix(management): improve error handling and normalize YAML comment indentation
Enhance error management for file operations and clean up temporary files. Add `NormalizeCommentIndentation` function to ensure YAML comments maintain consistent formatting.
This commit is contained in:
@@ -28,7 +28,7 @@ func (h *Handler) GetConfigYAML(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
var node yaml.Node
|
var node yaml.Node
|
||||||
if err := yaml.Unmarshal(data, &node); err != nil {
|
if err = yaml.Unmarshal(data, &node); err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "parse_failed", "message": err.Error()})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "parse_failed", "message": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -41,17 +41,18 @@ func (h *Handler) GetConfigYAML(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func WriteConfig(path string, data []byte) error {
|
func WriteConfig(path string, data []byte) error {
|
||||||
|
data = config.NormalizeCommentIndentation(data)
|
||||||
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
|
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := f.Write(data); err != nil {
|
if _, errWrite := f.Write(data); errWrite != nil {
|
||||||
f.Close()
|
_ = f.Close()
|
||||||
return err
|
return errWrite
|
||||||
}
|
}
|
||||||
if err := f.Sync(); err != nil {
|
if errSync := f.Sync(); errSync != nil {
|
||||||
f.Close()
|
_ = f.Close()
|
||||||
return err
|
return errSync
|
||||||
}
|
}
|
||||||
return f.Close()
|
return f.Close()
|
||||||
}
|
}
|
||||||
@@ -63,7 +64,7 @@ func (h *Handler) PutConfigYAML(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
var cfg config.Config
|
var cfg config.Config
|
||||||
if err := yaml.Unmarshal(body, &cfg); err != nil {
|
if err = yaml.Unmarshal(body, &cfg); err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid_yaml", "message": err.Error()})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid_yaml", "message": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -75,18 +76,20 @@ func (h *Handler) PutConfigYAML(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
tempFile := tmpFile.Name()
|
tempFile := tmpFile.Name()
|
||||||
if _, err := tmpFile.Write(body); err != nil {
|
if _, errWrite := tmpFile.Write(body); errWrite != nil {
|
||||||
tmpFile.Close()
|
_ = tmpFile.Close()
|
||||||
os.Remove(tempFile)
|
_ = os.Remove(tempFile)
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "write_failed", "message": err.Error()})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "write_failed", "message": errWrite.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := tmpFile.Close(); err != nil {
|
if errClose := tmpFile.Close(); errClose != nil {
|
||||||
os.Remove(tempFile)
|
_ = os.Remove(tempFile)
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "write_failed", "message": err.Error()})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "write_failed", "message": errClose.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer os.Remove(tempFile)
|
defer func() {
|
||||||
|
_ = os.Remove(tempFile)
|
||||||
|
}()
|
||||||
_, err = config.LoadConfigOptional(tempFile, false)
|
_, err = config.LoadConfigOptional(tempFile, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusUnprocessableEntity, gin.H{"error": "invalid_config", "message": err.Error()})
|
c.JSON(http.StatusUnprocessableEntity, gin.H{"error": "invalid_config", "message": err.Error()})
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
@@ -462,13 +463,19 @@ func SaveConfigPreserveComments(configFile string, cfg *Config) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer func() { _ = f.Close() }()
|
defer func() { _ = f.Close() }()
|
||||||
enc := yaml.NewEncoder(f)
|
var buf bytes.Buffer
|
||||||
|
enc := yaml.NewEncoder(&buf)
|
||||||
enc.SetIndent(2)
|
enc.SetIndent(2)
|
||||||
if err = enc.Encode(&original); err != nil {
|
if err = enc.Encode(&original); err != nil {
|
||||||
_ = enc.Close()
|
_ = enc.Close()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return enc.Close()
|
if err = enc.Close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
data = NormalizeCommentIndentation(buf.Bytes())
|
||||||
|
_, err = f.Write(data)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func sanitizeConfigForPersist(cfg *Config) *Config {
|
func sanitizeConfigForPersist(cfg *Config) *Config {
|
||||||
@@ -518,13 +525,40 @@ func SaveConfigPreserveCommentsUpdateNestedScalar(configFile string, path []stri
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer func() { _ = f.Close() }()
|
defer func() { _ = f.Close() }()
|
||||||
enc := yaml.NewEncoder(f)
|
var buf bytes.Buffer
|
||||||
|
enc := yaml.NewEncoder(&buf)
|
||||||
enc.SetIndent(2)
|
enc.SetIndent(2)
|
||||||
if err = enc.Encode(&root); err != nil {
|
if err = enc.Encode(&root); err != nil {
|
||||||
_ = enc.Close()
|
_ = enc.Close()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return enc.Close()
|
if err = enc.Close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
data = NormalizeCommentIndentation(buf.Bytes())
|
||||||
|
_, err = f.Write(data)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// NormalizeCommentIndentation removes indentation from standalone YAML comment lines to keep them left aligned.
|
||||||
|
func NormalizeCommentIndentation(data []byte) []byte {
|
||||||
|
lines := bytes.Split(data, []byte("\n"))
|
||||||
|
changed := false
|
||||||
|
for i, line := range lines {
|
||||||
|
trimmed := bytes.TrimLeft(line, " \t")
|
||||||
|
if len(trimmed) == 0 || trimmed[0] != '#' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if len(trimmed) == len(line) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
lines[i] = append([]byte(nil), trimmed...)
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
if !changed {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
return bytes.Join(lines, []byte("\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// getOrCreateMapValue finds the value node for a given key in a mapping node.
|
// getOrCreateMapValue finds the value node for a given key in a mapping node.
|
||||||
@@ -766,6 +800,7 @@ func matchSequenceElement(original []*yaml.Node, used []bool, target *yaml.Node)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
}
|
}
|
||||||
// Fallback to structural equality to preserve nodes lacking explicit identifiers.
|
// Fallback to structural equality to preserve nodes lacking explicit identifiers.
|
||||||
for i := range original {
|
for i := range original {
|
||||||
|
|||||||
Reference in New Issue
Block a user