97 lines
2.3 KiB
Go
97 lines
2.3 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"net/url"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type configFile struct {
|
|
Host string `json:"host,omitempty"`
|
|
Session string `json:"session,omitempty"`
|
|
ExpiresAt time.Time `json:"expiresAt,omitempty"`
|
|
}
|
|
|
|
func defaultConfigPath() string {
|
|
if value := os.Getenv("UFILE_CONFIG"); value != "" {
|
|
return value
|
|
}
|
|
dir, err := os.UserConfigDir()
|
|
if err != nil {
|
|
return "ufile-cli.json"
|
|
}
|
|
return filepath.Join(dir, "ufile-cli", "config.json")
|
|
}
|
|
|
|
func loadConfig(path string) (configFile, error) {
|
|
data, err := os.ReadFile(path)
|
|
if errors.Is(err, os.ErrNotExist) {
|
|
return configFile{}, nil
|
|
}
|
|
if err != nil {
|
|
return configFile{}, err
|
|
}
|
|
var config configFile
|
|
if err := json.Unmarshal(data, &config); err != nil {
|
|
return configFile{}, fmt.Errorf("配置文件格式错误: %w", err)
|
|
}
|
|
return config, nil
|
|
}
|
|
|
|
func saveConfig(path string, config configFile) error {
|
|
dir := filepath.Dir(path)
|
|
if err := os.MkdirAll(dir, 0o700); err != nil {
|
|
return err
|
|
}
|
|
data, err := json.MarshalIndent(config, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
data = append(data, '\n')
|
|
temp, err := os.CreateTemp(dir, ".config-*")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
tempName := temp.Name()
|
|
defer os.Remove(tempName)
|
|
if err := temp.Chmod(0o600); err != nil {
|
|
temp.Close()
|
|
return err
|
|
}
|
|
if _, err := temp.Write(data); err != nil {
|
|
temp.Close()
|
|
return err
|
|
}
|
|
if err := temp.Close(); err != nil {
|
|
return err
|
|
}
|
|
if err := os.Rename(tempName, path); err == nil {
|
|
return nil
|
|
}
|
|
if err := os.Remove(path); err != nil && !errors.Is(err, os.ErrNotExist) {
|
|
return err
|
|
}
|
|
return os.Rename(tempName, path)
|
|
}
|
|
|
|
func normalizeHost(value string) (string, error) {
|
|
value = strings.TrimSpace(value)
|
|
parsed, err := url.Parse(value)
|
|
if err != nil || parsed.Scheme == "" || parsed.Host == "" {
|
|
return "", fmt.Errorf("无效的服务地址 %q,需要包含 http:// 或 https://", value)
|
|
}
|
|
if parsed.Scheme != "http" && parsed.Scheme != "https" {
|
|
return "", fmt.Errorf("服务地址只支持 http 或 https")
|
|
}
|
|
if parsed.RawQuery != "" || parsed.Fragment != "" {
|
|
return "", fmt.Errorf("服务地址不能包含查询参数或片段")
|
|
}
|
|
parsed.Path = strings.TrimRight(parsed.Path, "/")
|
|
return strings.TrimRight(parsed.String(), "/"), nil
|
|
}
|