---
name: api-routing
description: API 路由注册规范。注册新 API 路由、添加新 Handler 时使用。包含 Register() 函数用法、RouteSpec 必填项、文档生成器更新等规范。
---

# API 路由注册规范

**所有 HTTP 接口必须使用统一的 `Register()` 函数注册，以自动加入 OpenAPI 文档生成。**

## 触发条件

在以下情况下必须遵守本规范：
- 注册新的 API 路由
- 修改现有路由配置
- **添加新的 Handler（必须同步更新文档生成器！）**

## 新增 Handler 检查清单（⚠️ 最容易遗漏）

新增 Handler 时，必须完成以下 **4 个步骤**，否则接口不会出现在 OpenAPI 文档中：

| 步骤 | 文件 | 操作 |
|------|------|------|
| 1️⃣ | `internal/bootstrap/types.go` | 添加 Handler 字段 |
| 2️⃣ | `internal/bootstrap/handlers.go` | 实例化 Handler |
| 3️⃣ | `internal/routes/admin.go` | 调用路由注册函数 |
| 4️⃣ | `cmd/api/docs.go` + `cmd/gendocs/main.go` | **添加到文档生成器** |

### 步骤 4 详解（最常遗漏！）

```go
// cmd/api/docs.go 和 cmd/gendocs/main.go 都要改！
handlers := &bootstrap.Handlers{
    // ... 现有 Handler
    IotCard:       admin.NewIotCardHandler(nil),       // 添加
    IotCardImport: admin.NewIotCardImportHandler(nil), // 添加
}
```

## 核心规则

### 必须使用 Register() 函数

```go
// ✅ 正确
Register(router, doc, basePath, "POST", "/shops", handler.Create, RouteSpec{
    Summary: "创建店铺",
    Tags:    []string{"店铺管理"},
    Input:   new(model.CreateShopRequest),
    Output:  new(model.ShopResponse),
    Auth:    true,
})

// ❌ 错误：直接注册不会生成文档
router.Post("/shops", handler.Create)
```

## RouteSpec 必填项

| 字段 | 类型 | 说明 | 示例 |
|------|------|------|------|
| `Summary` | string | 操作说明（中文，简短） | `"创建店铺"` |
| `Tags` | []string | 分类标签（用于文档分组） | `[]string{"店铺管理"}` |
| `Input` | interface{} | 请求 DTO（`nil` 表示无参数） | `new(model.CreateShopRequest)` |
| `Output` | interface{} | 响应 DTO（`nil` 表示无返回） | `new(model.ShopResponse)` |
| `Auth` | bool | 是否需要认证 | `true` |

## 常见路由模式

### CRUD 路由组

```go
// 列表查询
Register(router, doc, basePath, "GET", "/shops", handler.List, RouteSpec{
    Summary: "获取店铺列表",
    Tags:    []string{"店铺管理"},
    Input:   new(model.ListShopRequest),
    Output:  new(model.ShopListResponse),
    Auth:    true,
})

// 详情查询
Register(router, doc, basePath, "GET", "/shops/:id", handler.Get, RouteSpec{
    Summary: "获取店铺详情",
    Tags:    []string{"店铺管理"},
    Input:   new(model.IDReq),
    Output:  new(model.ShopResponse),
    Auth:    true,
})

// 创建
Register(router, doc, basePath, "POST", "/shops", handler.Create, RouteSpec{
    Summary: "创建店铺",
    Tags:    []string{"店铺管理"},
    Input:   new(model.CreateShopRequest),
    Output:  new(model.ShopResponse),
    Auth:    true,
})

// 更新
Register(router, doc, basePath, "PUT", "/shops/:id", handler.Update, RouteSpec{
    Summary: "更新店铺",
    Tags:    []string{"店铺管理"},
    Input:   new(model.UpdateShopRequest),
    Output:  new(model.ShopResponse),
    Auth:    true,
})

// 删除
Register(router, doc, basePath, "DELETE", "/shops/:id", handler.Delete, RouteSpec{
    Summary: "删除店铺",
    Tags:    []string{"店铺管理"},
    Input:   new(model.IDReq),
    Output:  nil,
    Auth:    true,
})
```

### 无认证路由

```go
// 公开接口（如健康检查）
Register(router, doc, basePath, "GET", "/health", handler.Health, RouteSpec{
    Summary: "健康检查",
    Tags:    []string{"系统"},
    Input:   nil,
    Output:  new(model.HealthResponse),
    Auth:    false,
})
```

## AI 助手检查清单

### 注册路由时

1. ✅ 是否使用 `Register()` 函数而非直接注册
2. ✅ `Summary` 是否使用中文简短描述
3. ✅ `Tags` 是否正确分组
4. ✅ `Input` 和 `Output` 是否指向正确的 DTO
5. ✅ `Auth` 是否根据业务需求正确设置

### 新增 Handler 时（⚠️ 必查）

1. ✅ `internal/bootstrap/types.go` 添加了 Handler 字段
2. ✅ `internal/bootstrap/handlers.go` 实例化了 Handler
3. ✅ `internal/routes/admin.go` 调用了路由注册函数
4. ✅ **`cmd/api/docs.go` 添加了 Handler**
5. ✅ **`cmd/gendocs/main.go` 添加了 Handler**
6. ✅ 运行 `go run cmd/gendocs/main.go` 验证文档生成
7. ✅ 运行 `grep "接口路径" docs/admin-openapi.yaml` 确认接口存在

**完整指南**: 参见 [`docs/api-documentation-guide.md`](docs/api-documentation-guide.md)
