Skip to content

Commit f680fb1

Browse files
committed
refactor(callback): 重构回调服务器以使用内部包
将 main.go 中的单一文件逻辑分解为多个内部包,以提高代码的模块化、可维护性和可测试性。 - `internal/config`: 处理配置加载。 - `internal/handler`: 包含 HTTP 请求处理程序。 - `internal/logger`: 提供结构化日志记录。 - `internal/signature`: 管理请求签名验证。 此更改遵循了关注点分离的原则,并更新了 README 以反映新的构建和运行说明。 refactor(callback): refactor callback server into internal packages Decompose the monolithic logic in main.go into several internal packages to improve modularity, maintainability, and testability. - `internal/config`: Handles configuration loading. - `internal/handler`: Contains the HTTP request handler. - `internal/logger`: Provides structured logging. - `internal/signature`: Manages request signature verification. This change promotes better separation of concerns and updates the README to reflect new build and run instructions.
1 parent c95f0a7 commit f680fb1

File tree

9 files changed

+544
-139
lines changed

9 files changed

+544
-139
lines changed

go/callback/README.md

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44

55
此工具提供了一个带签名验证的安全回调接口,用于触发 Docker 容器和卷的备份操作。
66

7+
## 完整使用指南
8+
9+
有关如何安装、配置和使用此回调服务器的完整指南,请参阅 [USAGE.md](USAGE.md) 文件。
10+
711
## 配置
812

913
在使用此回调服务器之前,您需要在项目根目录下的 `backup.conf` 文件中配置 `callback_secret`
@@ -18,20 +22,20 @@ callback_secret=your_secret_key_here
1822
`go/callback/` 目录中运行以下命令来编译服务器:
1923

2024
```bash
21-
go build -o ../../callback_server .
25+
go build -o callback_server.exe .
2226
```
2327

24-
这将在项目根目录生成一个名为 `callback_server` 的可执行文件。
28+
这将生成一个名为 `callback_server.exe` 的可执行文件(在 Windows 上)
2529

2630
## 运行服务器
2731

28-
切换到项目根目录并运行生成的可执行文件
32+
`go/callback/` 目录中运行生成的可执行文件
2933

3034
```bash
31-
./callback_server
35+
./callback_server.exe
3236
```
3337

34-
服务器将在 `localhost:8080` 启动。
38+
服务器将在 `localhost:47731` 启动。
3539

3640
## API 端点
3741

@@ -58,15 +62,15 @@ go build -o ../../callback_server .
5862
`go/callback/` 目录中运行以下命令来编译客户端示例:
5963

6064
```bash
61-
go build -o client_example client_example.go
65+
go build -o client_example.exe client_example.go
6266
```
6367

6468
由于 `client_example.go` 文件被构建标签 `//go:build ignore` 标记,所以编译时必须显式指定文件名。
6569

6670
然后可以使用以下命令来调用回调接口:
6771

6872
```bash
69-
./client_example -a --volumes
73+
./client_example.exe -a --volumes
7074
```
7175

7276
## Client Examples

go/callback/USAGE.md

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
# 回调服务器使用完整指南
2+
3+
## 目录
4+
5+
1. [简介](#简介)
6+
2. [系统要求](#系统要求)
7+
3. [安装和配置](#安装和配置)
8+
4. [编译和运行](#编译和运行)
9+
5. [API 接口说明](#api-接口说明)
10+
6. [客户端使用示例](#客户端使用示例)
11+
7. [错误处理和日志](#错误处理和日志)
12+
8. [安全注意事项](#安全注意事项)
13+
14+
## 简介
15+
16+
回调服务器是一个安全的 HTTP 服务,用于接收经过签名验证的请求以触发 Docker 容器和卷的备份操作。它使用 HMAC-SHA256 签名验证来确保请求的安全性。
17+
18+
## 系统要求
19+
20+
- Go 1.21 或更高版本
21+
- Docker 环境
22+
- Windows、Linux 或 macOS 操作系统
23+
24+
## 安装和配置
25+
26+
### 1. 配置文件设置
27+
28+
在项目根目录下的 `backup.conf` 文件中配置 `callback_secret`
29+
30+
```bash
31+
# backup.conf
32+
callback_secret=your_secret_key_here
33+
```
34+
35+
确保该密钥足够安全,建议使用随机生成的字符串。
36+
37+
### 2. 其他配置选项
38+
39+
`backup.conf` 文件还包含许多其他配置选项,用于控制备份行为:
40+
41+
- `DEFAULT_BACKUP_DIR`: 默认备份目录
42+
- `BACKUP_RETENTION_DAYS`: 备份文件保留天数
43+
- `COMPRESSION_FORMAT`: 备份压缩格式
44+
- 等等...
45+
46+
## 编译和运行
47+
48+
### 1. 编译服务器
49+
50+
`go/callback/` 目录中运行以下命令来编译服务器:
51+
52+
```bash
53+
go build -o callback_server .
54+
```
55+
56+
这将生成一个名为 `callback_server` 的可执行文件。
57+
58+
### 2. 运行服务器
59+
60+
`go/callback/` 目录中运行生成的可执行文件:
61+
62+
```bash
63+
./callback_server
64+
```
65+
66+
服务器将在 `localhost:47731` 启动,并显示类似以下的日志信息:
67+
68+
```json
69+
{
70+
"time": "2025-07-27T11:29:59.8830471+08:00",
71+
"level": "INFO",
72+
"msg": "Starting server",
73+
"port": "47731"
74+
}
75+
```
76+
77+
## API 接口说明
78+
79+
### `POST /backup`
80+
81+
此端点用于触发备份操作。
82+
83+
#### 请求头 (Headers)
84+
85+
- `X-Signature`: 请求签名,用于验证请求来源。签名是使用配置的 `callback_secret` 对请求体进行 HMAC-SHA256 计算得出的。
86+
87+
#### 请求体 (Request Body)
88+
89+
```json
90+
{
91+
"args": ["arg1", "arg2"]
92+
}
93+
```
94+
95+
- `args`: 传递给备份脚本的参数数组。
96+
97+
#### 响应格式
98+
99+
成功响应:
100+
101+
```json
102+
{
103+
"message": "Backup initiated successfully",
104+
"output": "备份脚本的输出内容"
105+
}
106+
```
107+
108+
错误响应:
109+
110+
```json
111+
{
112+
"error": "错误描述信息"
113+
}
114+
```
115+
116+
## 客户端使用示例
117+
118+
### 1. Go 客户端示例
119+
120+
编译客户端示例:
121+
122+
```bash
123+
go build -o client_example.exe client_example.go
124+
```
125+
126+
运行客户端:
127+
128+
```bash
129+
./client_example.exe -a --volumes
130+
```
131+
132+
### 2. Python 客户端示例
133+
134+
依赖安装:
135+
136+
```bash
137+
pip install requests
138+
```
139+
140+
运行命令:
141+
142+
```bash
143+
python client_example.py -a --volumes
144+
```
145+
146+
### 3. JavaScript (Node.js) 客户端示例
147+
148+
无需额外依赖,直接运行:
149+
150+
```bash
151+
node client_example.js -a --volumes
152+
```
153+
154+
### 4. TypeScript 客户端示例
155+
156+
依赖安装:
157+
158+
```bash
159+
npm install -g typescript ts-node
160+
```
161+
162+
运行命令:
163+
164+
```bash
165+
ts-node client_example.ts -a --volumes
166+
```
167+
168+
### 5. cURL 客户端示例
169+
170+
您也可以使用 `curl` 和其他命令行工具直接触发回调。这是一个一键执行的示例,它会自动从 `backup.conf` 读取密钥、生成签名并发起请求:
171+
172+
```bash
173+
# 注意:请在 go/callback 目录下运行此命令
174+
SECRET=$(grep 'callback_secret' ../../backup.conf | cut -d '"' -f 2)
175+
BODY='{"args": ["-a", "--volumes"]}'
176+
SIGNATURE=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -binary | base64)
177+
178+
curl -X POST \
179+
-H "Content-Type: application/json" \
180+
-H "X-Signature: $SIGNATURE" \
181+
-d "$BODY" \
182+
http://localhost:47731/backup
183+
```
184+
185+
## 错误处理和日志
186+
187+
### 日志格式
188+
189+
服务器使用结构化的 JSON 日志格式,包含以下字段:
190+
191+
- `time`: 时间戳
192+
- `level`: 日志级别(INFO, ERROR, WARN, DEBUG)
193+
- `msg`: 日志消息
194+
- 其他上下文信息
195+
196+
示例:
197+
198+
```json
199+
{
200+
"time": "2025-07-27T11:29:59.8830471+08:00",
201+
"level": "ERROR",
202+
"msg": "Error loading config",
203+
"error": "failed to read config file: open backup.conf: The system cannot find the file specified."
204+
}
205+
```
206+
207+
### 常见错误
208+
209+
1. **配置文件未找到**
210+
211+
- 确保 `backup.conf` 文件存在于 `go/callback/` 目录中
212+
- 日志会显示相应的错误信息
213+
214+
2. **签名验证失败**
215+
216+
- 响应:`{"error": "Invalid signature"}`
217+
- 确保客户端使用了正确的 `callback_secret` 生成签名
218+
219+
3. **请求方法不允许**
220+
221+
- 响应:`{"error": "Method not allowed"}`
222+
- 确保使用 POST 方法请求 `/backup` 端点
223+
224+
4. **JSON 解析错误**
225+
- 响应:`{"error": "Invalid JSON in request body"}`
226+
- 确保请求体是有效的 JSON 格式
227+
228+
## 安全注意事项
229+
230+
1. **密钥保护**
231+
232+
- 确保 `callback_secret` 足够复杂且安全
233+
- 不要在代码中硬编码密钥
234+
- 定期更换密钥
235+
236+
2. **网络访问控制**
237+
238+
- 在生产环境中,应限制对回调服务器的网络访问
239+
- 使用防火墙规则只允许特定 IP 地址访问
240+
241+
3. **HTTPS**
242+
243+
- 在生产环境中,建议使用 HTTPS 而不是 HTTP
244+
- 这可以防止签名在传输过程中被截获
245+
246+
4. **参数验证**
247+
- 客户端传递的参数会直接传递给备份脚本
248+
- 确保备份脚本对输入参数进行了适当的验证和清理
249+
250+
通过遵循以上指南,您可以安全有效地使用回调服务器来触发 Docker 备份操作。
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package config
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"strings"
7+
)
8+
9+
// Config 结构体用于存放所有配置项
10+
type Config struct {
11+
Port string
12+
ScriptPath string
13+
CallbackSecret string
14+
}
15+
16+
// LoadConfig 从指定路径读取配置文件并返回配置对象
17+
func LoadConfig(path string) (*Config, error) {
18+
// 默认配置值
19+
config := &Config{
20+
Port: "47731",
21+
ScriptPath: "docker-backup.sh",
22+
}
23+
24+
// 读取配置文件
25+
content, err := os.ReadFile(path)
26+
if err != nil {
27+
return nil, fmt.Errorf("failed to read config file: %w", err)
28+
}
29+
30+
// 解析配置文件
31+
lines := strings.Split(string(content), "\n")
32+
for _, line := range lines {
33+
// 跳过注释和空行
34+
trimmedLine := strings.TrimSpace(line)
35+
if trimmedLine == "" || strings.HasPrefix(trimmedLine, "#") {
36+
continue
37+
}
38+
39+
// 查找 callback_secret
40+
if strings.HasPrefix(trimmedLine, "callback_secret") {
41+
parts := strings.SplitN(trimmedLine, "=", 2)
42+
if len(parts) == 2 {
43+
config.CallbackSecret = strings.TrimSpace(parts[1])
44+
}
45+
}
46+
}
47+
48+
// 验证必要配置项
49+
if config.CallbackSecret == "" {
50+
return nil, fmt.Errorf("callback_secret not found in config file")
51+
}
52+
53+
return config, nil
54+
}

0 commit comments

Comments
 (0)