# udeServer 基于 [go-zero](https://go-zero.dev/) 的 HTTP API 服务。项目由 `goctl` 生成,包含示例接口、数据库连通性检查,以及 `t_directory`、`t_key`、`t_service` 三张表的完整 CRUD 接口。 ## 技术栈 | 组件 | 版本 | | --- | --- | | Go | 1.25.10 | | go-zero | v1.10.3 | | goctl | v1.10.2 | | MySQL | 8.4.4(10.10.10.30:3306/ude) | ## 目录结构 ``` . ├── udeServer.api # API 定义(接口的唯一事实来源) ├── udeserver.go # 程序入口 ├── etc/ │ └── udeserver-api.yaml # 配置文件 ├── internal/ │ ├── apierr/ # HTTP 状态码错误封装 │ ├── config/ # 配置结构体 │ ├── handler/ # HTTP handler 与路由注册 │ ├── logic/ # 业务逻辑 │ ├── model/ # goctl 生成的 model 与自定义查询 │ ├── svc/ # ServiceContext,管理依赖 │ └── types/ # 请求/响应类型 ├── go.mod └── go.sum ``` ## 环境说明 - Go 1.25.10 安装在 `C:\Users\Administrator\sdk\go1.25.10`;系统默认的 `go` 仍为 1.24.0。 - 已设置 `GOTOOLCHAIN=auto`,因此在 `go.mod` 要求 `go 1.25.10` 时,Go 会自动切换到 1.25.10,无需手动修改 PATH。 - `goctl` 安装在 `C:\Users\Administrator\go\bin\goctl.exe`,该目录未加入 PATH,下文使用完整路径调用。 - 若希望命令行直接使用 1.25.10,可将 `C:\Users\Administrator\sdk\go1.25.10\bin` 放到 PATH 最前面。 ## 快速开始 ```powershell # 下载依赖(首次执行会按 go.mod 自动获取 Go 1.25.10 工具链) go mod download # 启动服务,默认监听 0.0.0.0:9993 go run udeserver.go -f etc/udeserver-api.yaml # 另开终端验证 curl http://127.0.0.1:9993/api/v1/from/you # {"message":"Hello you"} curl http://127.0.0.1:9993/api/v1/db/ping # {"ok":true,"version":"8.4.4","database":"ude"} ``` 构建可执行文件: ```powershell go build -o bin/udeserver.exe udeserver.go .\bin\udeserver.exe -f etc\udeserver-api.yaml ``` ## API 接口 三张表各有一组 CRUD 接口: | 资源 | 新增 | 列表 | 详情 | 更新 | 删除 | | --- | --- | --- | --- | --- | --- | | 保护目录 `t_directory` | `POST /directories` | `GET /directories` | `GET /directories/:id` | `PUT /directories/:id` | `DELETE /directories/:id` | | 密钥 `t_key` | `POST /keys/create` | `POST /keys/list` | `POST /keys/detail` | `POST /keys/update` | `POST /keys/delete` | | 服务 `t_service` | `POST /services` | `GET /services` | `GET /services/:id` | `PUT /services/:id` | `DELETE /services/:id` | > 密钥接口已全部改为 `POST`,参数一律放请求体(`id` 也在 body 里,不再走路径)。 > 目录、服务接口仍是 REST 风格。 > 所有路由统一带 `/api/v1` 前缀,如 `GET /api/v1/keys/:id`。前缀在 `udeServer.api` 的 `@server(prefix: /api/v1)` 中配置,实际请求都需要加前缀;`/from/:name` 和 `/db/ping` 也不例外。 ### 统一响应格式 所有接口(成功/失败)HTTP 状态恒为 `200`,返回 `{code, message, data}` 封装: ```json { "code": 100000, "message": "操作成功", "data": { "ok": true } } ``` 业务码: | code | 含义 | | --- | --- | | 100000 | 操作成功 | | 100001 | 参数错误(如缺少 `name`、`id` 非法) | | 100002 | 资源不存在 | | 100003 | 服务器内部错误 | - 失败响应:`{"code":100xxx,"message":"错误描述","data":null}`,前端只需判断 `code`。 - 全局封装在 `udeserver.go` 的 `response.Register()` 中注册,实现见 `internal/response/`。 ### 分页 列表接口统一支持分页,`page` 默认 `1`,`pageSize` 默认 `10`(最大 `100`),响应 `data` 为 `{"list":[...],"total":13}`(超出范围时 `list` 为 `[]`): - 目录、服务:query 参数,`GET /api/v1/directories?page=2&pageSize=5` - 密钥:请求体参数,`POST /api/v1/keys/list`,body 为 `{"page":2,"pageSize":5,"name":"搜索词","status":"1"}`;`name` 可选、为空则不过滤,用 `LIKE` 模糊匹配(大小写不敏感,`%`、`_`、`\` 已做转义);`status` 可选,`"1"` 启用 / `"2"` 停用,非法取值返回 `100001` 服务接口示例: ```powershell # 新增服务:id 必填(t_service 主键没有 AUTO_INCREMENT) curl -X POST http://127.0.0.1:9993/api/v1/services ` -H "Content-Type: application/json" ` -d "{\"id\":1,\"name\":\"demo\",\"ip\":\"10.0.0.1\",\"port\":\"8080\",\"iden\":\"svc-1\",\"keyIden\":\"key-1\",\"keyAlgo\":\"AES\",\"status\":\"active\"}" # 列表 / 详情 curl http://127.0.0.1:9993/api/v1/services curl http://127.0.0.1:9993/api/v1/services/1 # 更新:id 放在路径中,请求体为完整字段 curl -X PUT http://127.0.0.1:9993/api/v1/services/1 ` -H "Content-Type: application/json" ` -d "{\"name\":\"demo-updated\",\"ip\":\"10.0.0.2\",\"port\":\"9090\",\"iden\":\"svc-1\",\"keyIden\":\"key-1\",\"keyAlgo\":\"SM4\",\"status\":\"disabled\"}" # 删除 curl -X DELETE http://127.0.0.1:9993/api/v1/services/1 ``` 密钥接口示例(全部为 `POST`,参数放请求体): ```powershell # 新增密钥:前端只需要传 name;id 自增、iden/content 服务端生成、status 默认 1、createAt 由数据库生成 curl -X POST http://127.0.0.1:9993/api/v1/keys/create ` -H "Content-Type: application/json" ` -d "{\"name\":\"demo-key\"}" # 分页列表:page/pageSize/name/status 都是可选的;name 为模糊匹配(LIKE,大小写不敏感,%/_ 会自动转义)、status 过滤 "1" 启用 / "2" 停用(其他取值返回 100001) curl -X POST http://127.0.0.1:9993/api/v1/keys/list ` -H "Content-Type: application/json" ` -d "{\"page\":1,\"pageSize\":10,\"name\":\"fuzz\",\"status\":\"1\"}" # 详情 curl -X POST http://127.0.0.1:9993/api/v1/keys/detail ` -H "Content-Type: application/json" ` -d "{\"id\":1}" # 更新状态:只允许更新 status,"1" 启用、"2" 停用;iden/name/content 不可改 curl -X POST http://127.0.0.1:9993/api/v1/keys/update ` -H "Content-Type: application/json" ` -d "{\"id\":1,\"status\":\"2\"}" # 删除 curl -X POST http://127.0.0.1:9993/api/v1/keys/delete ` -H "Content-Type: application/json" ` -d "{\"id\":1}" ``` 说明: - 密钥生成规则:`iden` 为去掉 `-` 的 UUIDv4;`content` 使用 PBKDF2-HMAC-SHA256(10 万次迭代、输出 32 字节、随机种子,`iden` 作盐)生成并转为十六进制;`status` 固定为 `"1"`;`id`、`create_at` 由数据库生成。 - 服务创建时 `id` 必填(`t_service` 主键没有 `AUTO_INCREMENT`);密钥接口如上全是 `POST` 请求体。 - `PUT`(目录/服务)为全量更新,未传的可选字段会写成 `NULL`(空字符串、`serviceId=0` 均按 `NULL` 处理);`POST /keys/update` 只更新 `status`(`"1"` 启用、`"2"` 停用,其他取值返回 `100001`),`iden/name/content` 不可改。 - 列表接口均已分页(见上),按 `id` 升序返回。 - 错误响应见「统一响应格式」一节,业务码 `100001~100003`。 ## 修改接口 1. 编辑 `udeServer.api`(新增 type、service、路由)。 2. 重新生成代码: ```powershell C:\Users\Administrator\go\bin\goctl.exe api go -api udeServer.api -dir . ``` `internal/logic` 下的已有业务逻辑不会被覆盖,可放心迭代 API 定义。 ## 生成 OpenAPI 文档(Apifox 导入) 1. 首次安装 swagger 插件(已装过可跳过): ```powershell go install github.com/zeromicro/goctl-swagger@latest ``` 2. 修改 `udeServer.api` 后重新生成(`doc` 目录不存在时须先创建,不会自动建目录): ```powershell New-Item -ItemType Directory -Force -Path doc | Out-Null C:\Users\Administrator\go\bin\goctl.exe api plugin --api udeServer.api --dir doc ^ -p 'goctl-swagger="swagger -filename udeServer-api.json -host 127.0.0.1:9993 -schemes http"' ``` 生成 `doc/udeServer-api.json`(Swagger 2.0 格式)。 3. Apifox 导入:**项目设置 → 导入数据 → OpenAPI/Swagger → 选择文件**上传即可,也可用 URL 方式导入本地文件。 说明: - 文档路径已带 `/api/v1` 前缀(来自 `@server(prefix: /api/v1)`),所以命令不要再传 `-basepath`,否则 Apifox 会把两者叠加成 `/api/v1/api/v1/`。 - 文档中的响应体为业务数据结构(如 `KeyResp`、`KeyListResp`),而实际接口统一封装为 `{code,message,data}`(见「统一响应格式」),导入后如需贴实际报文,可在 Apifox 中手动调整响应示例或加全局模板。 ## 配置 `etc/udeserver-api.yaml`: ```yaml Name: udeServer-api Host: 0.0.0.0 Port: 9993 MySQL: DataSource: "ude:H3G8xzfYpAASYFxF@tcp(10.10.10.30:3306)/ude?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai" ``` > 说明:goctl 生成的默认端口是 8888,当前配置使用 9993。 > > 数据库密码目前以明文写在配置中,请勿提交到公开仓库;生产环境建议使用环境变量或密钥管理服务注入。 go-zero 还支持在配置中开启日志、链路追踪、Prometheus 指标、限流等功能,按需在 `rest.RestConf` 基础上扩展 `internal/config/config.go` 即可。 ## 数据库 - 连接地址:`10.10.10.30:3306`,数据库 `ude`,账号 `ude` - 服务启动时通过 `sqlx.MustNewConn(c.MySQL)` 创建连接池(go-zero 默认 64 个连接,空闲回收 1 分钟) - `ServiceContext` 中的 `DB sqlx.SqlConn` 可直接在 logic 层使用: ```go var count int64 err := l.svcCtx.DB.QueryRowCtx(l.ctx, &count, "SELECT COUNT(*) FROM your_table") ``` - 已为三张表生成 model(`internal/model/`):`TDirectoryModel`、`TKeyModel`、`TServiceModel`,并在自定义 model 文件中补充了列表查询 `FindAll`。 - `t_directory`、`t_service` 的主键是普通 `int`,没有 `AUTO_INCREMENT`,新增时必须显式传 `id`;`t_key.id` 为自增主键,新增时不需要传。 - 新增表后可按表继续生成 model: ```powershell C:\Users\Administrator\go\bin\goctl.exe model mysql datasource ^ -url "ude:H3G8xzfYpAASYFxF@tcp(10.10.10.30:3306)/ude" ^ -table "your_table" -dir internal/model ``` ## 后续扩展 - 接入 Redis:在 `internal/config` 中增加 Redis 配置,并在 `internal/svc` 中初始化客户端。 - 拆分 RPC 服务:`goctl rpc new `,再在 `ServiceContext` 中注入 RPC 客户端。 - 多服务单仓库布局:将当前服务移动到 `app//api` 下,统一使用根 `go.mod` 管理。