# API Gateway

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

## 职责

- **路由转发**：`/api/v1/<service>/*` → 下游服务（iam / teacher-bff / student-bff / parent-bff / core-edu / content / msg / ai / data-ana）
- **JWT 鉴权**：RS256（IAM 签发，Gateway 通过 JWKS 公钥校验），DevMode 下支持 `dev-token` 旁路
- **请求 ID 注入**：生成或透传 `X-Request-Id`（`req-<uuid-v4>` 格式），全链路追踪
- **限流**：基于令牌桶的 per-IP 限流（100 rps，突发 20），超限返回 429 + `GW_RATE_LIMITED`
- **熔断**：基于 gobreaker v2 的下游服务熔断，5xx 错误率 > 50% 触发 OPEN，返回 503 + `GW_CIRCUIT_OPEN`
- **可观测性**：slog 结构化日志 + 7 个业务 metrics + OpenTelemetry tracer（资源属性完整）
- **CORS / 安全头 / Recovery**：标准化中间件链

## 中间件链

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

```
Request → Recovery → OTel → RequestID → CORS → SecurityHeaders → RequestBodyLimit → RateLimit
  → [api/v1 组] CircuitBreaker → AuthMiddleware(RS256) → Metrics → Proxy → Response
```

| 中间件          | 文件                                     | 职责                                                                   |
| --------------- | ---------------------------------------- | ---------------------------------------------------------------------- |
| Recovery        | `internal/middleware/recovery.go`        | panic 兜底返回 500 + `GW_INTERNAL_ERROR`                               |
| OTel            | `otelgin.Middleware`                     | OpenTelemetry 自动埋点                                                 |
| RequestID       | `internal/middleware/requestid.go`       | 生成/透传 `X-Request-Id`（`req-<uuid-v4>`）                            |
| CORS            | `internal/middleware/cors.go`            | 跨域允许（从 Config 读取白名单）                                       |
| SecurityHeaders | `internal/middleware/security.go`        | 安全响应头 + 请求体限制（413 `GW_REQUEST_TOO_LARGE`）                  |
| RateLimit       | `internal/middleware/ratelimit.go`       | per-IP 令牌桶限流，超限 429 `GW_RATE_LIMITED`                          |
| CircuitBreaker  | `internal/middleware/circuit-breaker.go` | 下游 5xx 错误率 > 50% 触发熔断，503 `GW_CIRCUIT_OPEN`                  |
| Auth            | `internal/middleware/auth.go`            | JWT RS256 校验（JWKS），注入 `x-user-id`/`x-user-roles`/`x-data-scope` |
| Metrics         | `internal/observability/metrics.go`      | HTTP 请求计数 + 延迟统计（7 个业务指标）                               |

## 路由表

| 前缀                         | 目标服务    | 端口 | 鉴权                                 |
| ---------------------------- | ----------- | ---- | ------------------------------------ |
| `/api/v1/iam/*`              | iam         | 3002 | JWT（register/login/refresh 白名单） |
| `/api/v1/teacher/*`          | teacher-bff | 3003 | JWT                                  |
| `/api/v1/student/*`          | student-bff | 3009 | JWT                                  |
| `/api/v1/parent/*`           | parent-bff  | 3010 | JWT                                  |
| `/api/v1/classes/*`          | core-edu    | 3004 | JWT                                  |
| `/api/v1/exams/*`            | core-edu    | 3004 | JWT                                  |
| `/api/v1/homework/*`         | core-edu    | 3004 | JWT                                  |
| `/api/v1/grades/*`           | core-edu    | 3004 | JWT                                  |
| `/api/v1/textbooks/*`        | content     | 3005 | JWT                                  |
| `/api/v1/chapters/*`         | content     | 3005 | JWT                                  |
| `/api/v1/knowledge-points/*` | content     | 3005 | JWT                                  |
| `/api/v1/questions/*`        | content     | 3005 | JWT                                  |
| `/api/v1/notifications/*`    | msg         | 3007 | JWT                                  |
| `/api/v1/messages/*`         | msg         | 3007 | JWT                                  |
| `/api/v1/ai/*`               | ai          | 3008 | JWT                                  |
| `/api/v1/analytics/*`        | data-ana    | 3006 | JWT                                  |
| `/api/v1/dashboard/*`        | data-ana    | 3006 | JWT                                  |

## 健康检查

| 端点           | 用途                                                       | 鉴权 |
| -------------- | ---------------------------------------------------------- | ---- |
| `GET /healthz` | 存活探针（liveness）                                       | 无   |
| `GET /readyz`  | 就绪探针（readiness，并行 ping 下游 /healthz，软失败规则） | 无   |
| `GET /metrics` | Prometheus 指标端点（7 个业务指标 + Go runtime）           | 无   |

## 开发

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

DevMode（接受 `Bearer dev-token` 旁路鉴权）：

```bash
DEV_MODE=true go run main.go
```

## 测试

```bash
cd services/api-gateway
go test ./internal/middleware/... -v -cover
```

## 构建

```bash
go build ./...
docker build -t edu/api-gateway .
```

## 配置

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

| 变量                          | 默认值                                      | 说明                                                     |
| ----------------------------- | ------------------------------------------- | -------------------------------------------------------- |
| `API_GATEWAY_PORT`            | 8080                                        | 监听端口                                                 |
| `ENV`                         | development                                 | 部署环境（production 时 W7 防护生效）                    |
| `DEV_MODE`                    | false                                       | 开发模式旁路：true 时接受 `Bearer dev-token`（仅非生产） |
| `IAM_JWKS_URL`                | http://localhost:3002/.well-known/jwks.json | RS256 公钥端点（非 DevMode 必填）                        |
| `JWT_ISSUER`                  | next-edu-cloud                              | JWT 签发者校验                                           |
| `JWT_AUDIENCE`                | next-edu-cloud                              | JWT 受众校验                                             |
| `CORS_ORIGINS`                | （空，用开发默认白名单）                    | CORS 白名单（逗号分隔）                                  |
| `CLASSES_SERVICE_URL`         | http://localhost:3001                       | classes 服务地址（遗留，路由实际走 core-edu）            |
| `IAM_SERVICE_URL`             | http://localhost:3002                       | iam 服务地址                                             |
| `TEACHER_BFF_URL`             | http://localhost:3003                       | teacher-bff 服务地址                                     |
| `STUDENT_BFF_URL`             | http://localhost:3009                       | student-bff 服务地址                                     |
| `PARENT_BFF_URL`              | http://localhost:3010                       | parent-bff 服务地址                                      |
| `CORE_EDU_SERVICE_URL`        | http://localhost:3004                       | core-edu 服务地址                                        |
| `CONTENT_SERVICE_URL`         | http://localhost:3005                       | content 服务地址                                         |
| `DATA_ANA_SERVICE_URL`        | http://localhost:3006                       | data-ana 服务地址                                        |
| `MSG_SERVICE_URL`             | http://localhost:3007                       | msg 服务地址                                             |
| `AI_SERVICE_URL`              | http://localhost:3008                       | ai 服务地址                                              |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | http://localhost:4318                       | OpenTelemetry OTLP 端点                                  |
| `LOG_LEVEL`                   | info                                        | 日志级别                                                 |

> **生产环境警告**：`DEV_MODE=true` 且 `ENV=production` 时服务 panic 拒绝启动（W7 防护）。

## 关联文档

- [架构影响地图](../../docs/architecture/004_architecture_impact_map.md)
- [项目规则](../../.trae/rules/project_rules.md)
- [模块理解确认书](./docs/01-understanding.md)
- [架构设计文档](./docs/02-architecture-design.md)
- [P6 硬化 Runbook](../../docs/architecture/runbooks/p6-hardening.md)
- [Helm Chart](../../infra/k8s/helm/api-gateway/)
