用户报告保存配置时出现错误:
保存失败:Unexpected non-whitespace character after JSON at position 4 (line 1 column 5)
根本原因:服务器返回了非 JSON 格式的响应,前端无法解析。
// 替换默认的 gin.Recovery() 为自定义 JSON 错误恢复
s.router.Use(gin.CustomRecovery(func(c *gin.Context, err any) {
c.JSON(http.StatusInternalServerError, gin.H{
"error": fmt.Sprintf("Internal server error: %v", err),
})
c.Abort()
}))
// 改为接收 map[string]interface{} 支持部分字段更新
func (cm *ConfigManager) UpdateDHCPConfig(updates map[string]interface{}) error
func (cm *ConfigManager) UpdateDNSConfig(updates map[string]interface{}) error
// 通过中间件注入 ConfigManager 到上下文
s.router.Use(func(c *gin.Context) {
c.Set("configManager", s.configManager)
c.Next()
})
s.router.GET("/api/health", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"status": "ok", "message": "Server is running"})
})
const contentType = response.headers.get('content-type');
if (!contentType || !contentType.includes('application/json')) {
const text = await response.text();
console.error('Non-JSON response:', text);
alert('服务器返回了非 JSON 格式响应,请查看控制台');
return;
}
try {
const response = await fetch('/api/dhcp/config', {...});
const data = await response.json();
if (response.ok) {
alert('配置已保存');
} else {
alert('保存失败:' + (data.error || '未知错误'));
}
} catch (error) {
console.error('Save error:', error);
alert('保存失败:' + error.message);
}
type DHCPConfig struct {
Enabled bool `json:"enabled"`
Interface string `json:"interface"`
Network string `json:"network"`
Netmask string `json:"netmask"`
Gateway string `json:"gateway"`
DNSServers []string `json:"dns_servers"`
NTPServers []string `json:"ntp_servers"`
BroadcastAddress string `json:"broadcast_address"`
LeaseTime int `json:"lease_time"`
IPPoolStart string `json:"ip_pool_start"`
IPPoolEnd string `json:"ip_pool_end"`
DomainName string `json:"domain_name"`
ExcludedIPs []string `json:"excluded_ips"`
}
type DNSConfig struct {
Enabled bool `json:"enabled"`
ListenAddr string `json:"listen_addr"`
ListenPort int `json:"listen_port"`
Upstream []string `json:"upstream"`
CacheSize int `json:"cache_size"`
CacheTTL int `json:"cache_ttl"`
Recursion bool `json:"recursion"`
AllowQuery []string `json:"allow_query"`
DNSSECValidation bool `json:"dnssec_validation"`
}
| 文件 | 修改内容 |
|---|---|
internal/web/server.go |
添加自定义恢复中间件、ConfigManager 注入、健康检查端点 |
internal/web/config_handler.go |
改为部分更新支持、完善错误处理 |
internal/config/config.go |
添加完整配置字段 |
cmd/main.go |
添加 ConfigManager 初始化 |
web/static/js/app.js |
增强错误处理、响应类型验证 |
configs/config.json |
更新为完整配置示例 |
cd /vol1/@apphome/trim.openclaw/data/workspace/dhcp-dns-manager
./test-api.sh
# 健康检查
curl http://localhost:8080/api/health
# 获取 DHCP 配置
curl -H "X-Session-ID: test" http://localhost:8080/api/dhcp/config
# 更新 DHCP 配置
curl -X PUT -H "X-Session-ID: test" \
-H "Content-Type: application/json" \
-d '{"network":"192.168.1.0"}' \
http://localhost:8080/api/dhcp/config
cd /vol1/@apphome/trim.openclaw/data/workspace/dhcp-dns-manager
sudo ./install.sh
查看服务器日志:
sudo journalctl -u dhcp-dns-manager -f
查看浏览器控制台:
运行测试脚本:
./test-api.sh
检查配置文件:
cat /opt/dhcp-dns-manager/configs/config.json | python3 -m json.tool
修复日期: 2026-04-23
版本: v0.2.1
状态: ✅ 已修复