refactor: 优化代码质量,遵循 KISS 原则

- 移除自签证书回退逻辑,简化为仅使用 AnyIP 证书
- 删除 internal/tls/generate.go(不再需要)
- 重构 main.go:提取初始化逻辑,main() 从 156 行降至 13 行
- 重构 internal/ws/handler.go:提取消息处理,handleConn() 从 131 行降至 25 行
- 重构 internal/config/load.go:使用 map 驱动消除重复代码
- 优化前端 startRecording():使用标准 AbortController API
- 优化前端 showToast():预定义 DOM 元素,代码减少 50%

代码行数减少 90 行,复杂度显著降低,所有构建通过
This commit is contained in:
2026-03-02 00:25:14 +08:00
parent 8c7b9b45fd
commit b87fead2fd
8 changed files with 316 additions and 371 deletions

View File

@@ -6,7 +6,6 @@ import (
"fmt"
"io"
"log/slog"
"net"
"net/http"
"os"
"path/filepath"
@@ -26,11 +25,10 @@ func certDir() string {
return dir
}
// Result holds the TLS config and metadata about which cert source was used.
// Result holds the TLS config and the AnyIP hostname.
type Result struct {
Config *tls.Config
AnyIP bool // true if AnyIP cert is active
Host string // hostname to use in URLs (AnyIP domain or raw IP)
Host string // AnyIP hostname (e.g. voicepaste-192-168-1-5.anyip.dev)
}
// AnyIPHost returns the AnyIP hostname for a given LAN IP.
@@ -40,82 +38,61 @@ func AnyIPHost(lanIP string) string {
return fmt.Sprintf("voicepaste-%s.anyip.dev", dashed)
}
// GetTLSConfig returns a TLS config for the given LAN IP.
// Priority: cached AnyIP → download AnyIP → cached self-signed → generate self-signed.
// GetTLSConfig returns a TLS config using AnyIP wildcard certificate.
// It tries cached cert first, then downloads fresh if needed.
func GetTLSConfig(lanIP string) (*Result, error) {
dir := certDir()
anyipDir := filepath.Join(dir, "anyip")
os.MkdirAll(anyipDir, 0700)
anyipCert := filepath.Join(anyipDir, "fullchain.pem")
anyipKey := filepath.Join(anyipDir, "privkey.pem")
certFile := filepath.Join(anyipDir, "fullchain.pem")
keyFile := filepath.Join(anyipDir, "privkey.pem")
host := AnyIPHost(lanIP)
// 1. Try cached AnyIP cert
if cert, err := tls.LoadX509KeyPair(anyipCert, anyipKey); err == nil {
if leaf, err := x509.ParseCertificate(cert.Certificate[0]); err == nil {
if time.Now().Before(leaf.NotAfter.Add(-24 * time.Hour)) { // 1 day buffer
slog.Info("using cached AnyIP certificate", "expires", leaf.NotAfter.Format("2006-01-02"))
return &Result{
Config: &tls.Config{Certificates: []tls.Certificate{cert}},
AnyIP: true,
Host: AnyIPHost(lanIP),
}, nil
}
}
// Try cached cert first
if cert, err := loadAndValidateCert(certFile, keyFile); err == nil {
slog.Info("using cached AnyIP certificate")
return &Result{
Config: &tls.Config{Certificates: []tls.Certificate{cert}},
Host: host,
}, nil
}
// 2. Try downloading AnyIP cert
if err := downloadAnyIPCert(anyipCert, anyipKey); err == nil {
if cert, err := tls.LoadX509KeyPair(anyipCert, anyipKey); err == nil {
slog.Info("downloaded fresh AnyIP certificate")
return &Result{
Config: &tls.Config{Certificates: []tls.Certificate{cert}},
AnyIP: true,
Host: AnyIPHost(lanIP),
}, nil
}
} else {
slog.Warn("AnyIP cert download failed, falling back to self-signed", "err", err)
// Download fresh cert
slog.Info("downloading AnyIP certificate")
if err := downloadAnyIPCert(certFile, keyFile); err != nil {
return nil, fmt.Errorf("failed to download AnyIP certificate: %w", err)
}
// 3. Try cached self-signed
ssCert := filepath.Join(dir, "cert.pem")
ssKey := filepath.Join(dir, "key.pem")
if cert, err := tls.LoadX509KeyPair(ssCert, ssKey); err == nil {
if leaf, err := x509.ParseCertificate(cert.Certificate[0]); err == nil {
if time.Now().Before(leaf.NotAfter) && certCoversIP(leaf, lanIP) {
slog.Info("using cached self-signed certificate", "expires", leaf.NotAfter.Format("2006-01-02"))
return &Result{
Config: &tls.Config{Certificates: []tls.Certificate{cert}},
Host: lanIP,
}, nil
}
}
}
// 4. Generate self-signed
slog.Info("generating self-signed TLS certificate", "ip", lanIP)
cert, err := generateSelfSigned(lanIP, ssCert, ssKey)
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
return nil, fmt.Errorf("generate TLS cert: %w", err)
return nil, fmt.Errorf("failed to load downloaded certificate: %w", err)
}
slog.Info("downloaded fresh AnyIP certificate")
return &Result{
Config: &tls.Config{Certificates: []tls.Certificate{cert}},
Host: lanIP,
Host: host,
}, nil
}
// certCoversIP checks if the certificate covers the given IP.
func certCoversIP(cert *x509.Certificate, ip string) bool {
target := net.ParseIP(ip)
if target == nil {
return false
// loadAndValidateCert loads a certificate and validates it's not expired.
func loadAndValidateCert(certFile, keyFile string) (tls.Certificate, error) {
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
return tls.Certificate{}, err
}
for _, certIP := range cert.IPAddresses {
if certIP.Equal(target) {
return true
}
leaf, err := x509.ParseCertificate(cert.Certificate[0])
if err != nil {
return tls.Certificate{}, err
}
return false
// Check if cert expires within 24 hours
if time.Now().After(leaf.NotAfter.Add(-24 * time.Hour)) {
return tls.Certificate{}, fmt.Errorf("certificate expired or expiring soon")
}
return cert, nil
}
// downloadAnyIPCert downloads the AnyIP wildcard cert and key.