# API Gateway

Go (Gin) 实现的 API 网关，所有外部请求的统一入口。

## 职责

- **路由转发**：`/api/v1/classes/*` → classes 服务（P1），后续阶段追加 iam/core-edu/content/msg 等路由
- **JWT 鉴权**：P1 HS256（测试密钥），P2 起 RS256（IAM 签发，Gateway 公钥校验）
- **请求 ID 注入**：生成或透传 `X-Request-ID`，全链路追踪
- **限流**（P6）：基于令牌桶的 per-IP 限流，超限返回 429
- **熔断**（P6）：基于 gobreaker v2 的下游服务熔断，5xx 错误率 > 50% 触发 OPEN
- **CORS / 安全头 / Recovery**（P6）：标准化中间件链

## 中间件链（P6）

请求处理顺序（自外向内）：

```
Request → RequestID → CORS → Security → Recovery → RateLimit → Auth → CircuitBreaker → Proxy → Response
```

| 中间件         | 文件                                     | 职责                                         |
| -------------- | ---------------------------------------- | -------------------------------------------- |
| RequestID      | `internal/middleware/requestid.go`       | 生成/透传 `X-Request-ID`                     |
| CORS           | `internal/middleware/cors.go`            | 跨域允许                                     |
| Security       | `internal/middleware/security.go`        | 安全响应头（X-Content-Type-Options 等）      |
| Recovery       | `internal/middleware/recovery.go`        | panic 兜底返回 500                           |
| RateLimit      | `internal/middleware/ratelimit.go`       | per-IP 令牌桶限流，超限 429                  |
| Auth           | `internal/middleware/auth.go`            | JWT 校验，注入 `x-user-id`/`x-user-roles` 头 |
| CircuitBreaker | `internal/middleware/circuit-breaker.go` | 下游 5xx 错误率 > 50% 触发熔断，返回 503     |

## 健康检查

| 端点           | 用途                                     | 鉴权 |
| -------------- | ---------------------------------------- | ---- |
| `GET /healthz` | 存活探针（liveness）                     | 无   |
| `GET /readyz`  | 就绪探针（readiness）                    | 无   |
| `GET /health`  | 兼容端点（返回 `{ status, timestamp }`） | 无   |

## 开发

```bash
cd services/api-gateway
go mod tidy
go run main.go
```

## 测试

```bash
# 单元 + 集成测试
cd services/api-gateway
go test ./internal/middleware/... -v -cover

# 测试覆盖
# - circuit-breaker_test.go: 5 用例（ClosedToOpen / OpenToHalfOpen / HalfOpenToClosed / HalfOpenToOpen / 4xxNotCounted）
# - ratelimit_test.go: 5 用例（AllowUnderBurst / RejectOverBurst / RefillTokens / PerIPIsolation / CleanupExpiredBuckets）
```

## 构建

```bash
# 本地构建
go build ./...

# Docker 构建
docker build -t edu/api-gateway .
```

## 配置

通过环境变量配置（见 `internal/config/config.go`）：

| 变量                          | 默认值                | 说明                                                   |
| ----------------------------- | --------------------- | ------------------------------------------------------ |
| `API_GATEWAY_PORT`            | 8080                  | 监听端口                                               |
| `JWT_SECRET`                  | （必填）              | HS256 签名密钥（P1）                                   |
| `JWT_ISSUER`                  | next-edu-cloud        | JWT 签发者                                             |
| `JWT_AUDIENCE`                | next-edu-cloud        | JWT 受众                                               |
| `DEV_MODE`                    | false                 | 开发模式旁路：true 时接受 `Bearer dev-token`（仅本地） |
| `CLASSES_SERVICE_URL`         | http://localhost:3001 | classes 服务地址                                       |
| `IAM_SERVICE_URL`             | http://localhost:3002 | iam 服务地址                                           |
| `TEACHER_BFF_URL`             | http://localhost:3003 | teacher-bff 服务地址                                   |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | http://localhost:4318 | OpenTelemetry OTLP 端点                                |
| `LOG_LEVEL`                   | info                  | 日志级别                                               |

> **生产环境警告**：`DEV_MODE` 必须为 `false` 或不设。设为 `true` 会允许 `dev-token` 旁路鉴权并注入固定 admin 身份。

## 关联文档

- [架构影响地图](../../docs/architecture/004_architecture_impact_map.md)
- [项目规则](../../.trae/rules/project_rules.md)
- [P6 硬化 Runbook](../../docs/architecture/runbooks/p6-hardening.md)
- [P6 后续工作手册](../../docs/architecture/runbooks/post-p6-followup.md)
- [Helm Chart](../../infra/k8s/helm/api-gateway/)
