简介
本技术文档围绕 DouPHP 的 API 路由系统展开,重点说明 ApiResolver 的 RESTful 路由设计原则、HTTP 动词映射与资源路由规范、版本控制策略;用户认证中间件的实现机制(JWT 令牌验证、会话管理与权限检查);限流中间件的流量控制算法及防 DDoS/滥用防护策略;并给出 API 文档自动生成、Swagger 集成与接口测试工具的使用建议。最后提供 API 路由最佳实践、错误码规范与性能优化建议。
项目结构
API 入口位于 api/index.php,通过设置路由委托给 Api\Foundation\Routing\Router,再由 Router 调用 ApiResolver 解析请求为分发计划,最终交由 Dispatcher 在中间件管道中执行。鉴权与限流等横切能力以中间件形式挂载,认证模式与白名单由 api/init/middleware.php 集中声明。
graph TB
Client["客户端"] --> Entry["api/index.php"]
Entry --> Router["Api\\Foundation\\Routing\\Router"]
Router --> Resolver["Api\\Foundation\\Routing\\ApiResolver"]
Resolver --> Dispatcher["Core Web Dispatcher"]
Dispatcher --> MW["中间件栈<br/>安全头/代理信任/限流/用户认证"]
MW --> Controller["业务控制器"]
Controller --> Response["ApiResponse JSON"]
图表来源
- index.php:27-35
- Router.php:43-67
- ApiResolver.php:60-90
章节来源
- index.php:14-55
- Router.php:28-67
- ApiResolver.php:30-90
核心组件
- ApiResolver:将当前请求解析为 DispatchPlan,负责 URL 命中、方法过滤、模块可用性校验、中间件栈组装。
- Router:薄壳调度器,统一处理未匹配与方法不允许场景,返回标准 JSON 错误。
- UserAuthMiddleware:从 Authorization: Bearer 提取 token,调用 auth('api') 解析登录态与工作身份,拒绝时返回 401/403。
- ThrottleMiddleware:按 IP 对敏感写接口与公共匿名写接口进行限流,超限返回 429。
- middleware.php:集中声明各模块/动作的鉴权模式(public/optional/required)与工作端强制策略。
- ApiCodes:统一的业务错误码常量集合,对外契约稳定。
章节来源
- ApiResolver.php:40-107
- Router.php:36-67
- UserAuthMiddleware.php:25-93
- ThrottleMiddleware.php:25-90
- middleware.php:18-146
- ApiCodes.php:21-74
架构总览
API 请求进入后,先由入口剥离 route 参数并注入 Request,随后 Router 委托 ApiResolver 解析。ApiResolver 使用后端声明式匹配器按 module/action 与 HTTP 方法匹配路由,产出包含控制器类、方法与路径参数的 DispatchPlan,并组合默认与路由级中间件。Dispatcher 依次执行中间件与控制器,最终输出 ApiResponse JSON。
sequenceDiagram
participant C as "客户端"
participant E as "api/index.php"
participant R as "Router"
participant A as "ApiResolver"
participant D as "Dispatcher"
participant M as "中间件栈"
participant Ctrl as "控制器"
C->>E : GET /api/?route=user/login
E->>R : dispatch()
R->>A : resolve(request, container)
A-->>R : DispatchPlan(控制器, 方法, 参数, 中间件)
R->>D : run(plan, container)
D->>M : 执行安全头/代理信任/限流/认证
M->>Ctrl : 调用业务方法
Ctrl-->>D : ApiResponse
D-->>R : Response
R-->>E : Response
E-->>C : JSON 响应
图表来源
- index.php:27-38
- Router.php:43-67
- ApiResolver.php:60-90
详细组件分析
ApiResolver:RESTful 路由设计与版本控制
- 路由形态:采用 ?route=module[/id][/action] 的查询参数形态,URL 中的数字段作为 id 路径参数。
- HTTP 动词映射:通过后端声明式匹配器按 HTTP 方法过滤,未接受的方法返回 405 JSON。
- 资源路由规范:路由文件使用 Route::group/prefix/sub/get/post 等声明式 API,支持子控制器与命名空间组织。
- 版本控制策略:当前代码库未发现显式的版本前缀或版本协商逻辑;如需版本化,建议在路由层增加版本分组(如 v1/v2),并在 ApiResolver 中按版本选择匹配器或中间件策略。
flowchart TD
Start(["请求进入"]) --> Parse["解析 route 字符串"]
Parse --> Match{"是否命中路由?"}
Match -- 否 --> NotFound["返回 404 JSON"]
Match -- 是 --> MethodCheck{"HTTP 方法允许?"}
MethodCheck -- 否 --> MethodNotAllowed["返回 405 JSON"]
MethodCheck -- 是 --> ModuleGate{"模块可用?"}
ModuleGate -- 否 --> DomainError["抛出领域异常"]
ModuleGate -- 是 --> BuildPlan["构建 DispatchPlan"]
BuildPlan --> End(["交给 Dispatcher 执行"])
图表来源
- ApiResolver.php:60-90
- Router.php:48-60
章节来源
- ApiResolver.php:30-107
- user.php:35-70
用户认证中间件:JWT 令牌验证、会话管理与权限检查
- 令牌来源:从 Authorization: Bearer <token> 请求头中提取 token。
- 登录态解析:调用 auth('api')->resolveUserContext(token) 解析上下文,并通过 hydrate 注入到后续流程。
- 工作端身份:当配置要求 work_required 时,额外校验 workId 是否有效。
- 拒绝策略:未认证返回 401,无工作端权限返回 403,均输出标准 JSON。
sequenceDiagram
participant MW as "UserAuthMiddleware"
participant Auth as "auth('api')"
participant Req as "Request"
participant Resp as "ApiResponse"
MW->>Req : bearerToken()
MW->>Auth : resolveUserContext(token)
Auth-->>MW : context(ok|fail)
alt 认证成功
MW->>Auth : hydrate(context)
MW-->>Next : 继续执行
else 未认证
MW->>Resp : error(UNAUTHORIZED, 401)
Resp-->>MW : send()
MW-->>Client : 401 JSON
end
Note over MW,Auth : 若 work_required,则额外校验 workId
图表来源
- UserAuthMiddleware.php:47-93
章节来源
- UserAuthMiddleware.php:25-93
- middleware.php:18-146
限流中间件:流量控制算法与防 DDoS/滥用策略
- 限流维度:按 IP 维度对敏感写接口与公共匿名写接口进行限流。
- 配额策略:针对登录、注册、短信验证码、留言、咨询、邮件订阅、防伪查询、LLM 成本端点等定义 max/window 配额。
- 超限处理:返回 429 JSON,并附带 Retry-After 头部提示重试时间。
- 防滥用:对高频写接口与高成本接口(如聊天流式接口)收紧配额,避免被恶意刷量。
flowchart TD
S["请求进入限流"] --> Key["计算限流键(IP + 路由)"]
Key --> Lookup{"是否存在配额?"}
Lookup -- 否 --> Pass["放行"]
Lookup -- 是 --> Check{"是否超过窗口内次数?"}
Check -- 否 --> Pass
Check -- 是 --> Reject["返回 429 + Retry-After"]
图表来源
- ThrottleMiddleware.php:33-90
章节来源
- ThrottleMiddleware.php:25-90
路由声明与资源路由规范
- 资源路由:使用 Route::resource 生成标准 RESTful 路由(仅暴露 index/show)。
- 分组与前缀:Route::group + prefix/sub 组织模块与子控制器,便于维护与权限控制。
- 命名:统一以 api. 前缀命名路由,便于调试与日志追踪。
示例参考:
- user 模块:主控制器覆盖会员中心/登录注册/找回密码/资料/SNS/地区/文件等动作;weixin/work/contact 子控制器分别承载微信相关、工作端与联系人管理。
- solution/support 模块:仅暴露列表与详情。
章节来源
- user.php:35-70
- solution.php:25-31
依赖关系分析
- Router 依赖 ApiResolver 与 Dispatcher,统一处理错误与响应。
- ApiResolver 依赖后端声明式匹配器、MethodResolver、MiddlewareRegistry,以及容器与配置。
- 中间件依赖抽象基类(AbstractUserAuthMiddleware、AbstractThrottleMiddleware),并通过 ApiResponse 输出标准 JSON。
- 错误码由 ApiCodes 统一管理,保证前后端契约一致。
classDiagram
class Router {
+dispatch() Response
}
class ApiResolver {
+resolve(Request, Container) DispatchPlan
-defaultAliases() string[]
}
class UserAuthMiddleware {
#configFile() string
#resolveContext() array
#inject(array) void
#hasWorkIdentity() bool
#rejectUnauthenticated() void
#rejectForbidden() void
}
class ThrottleMiddleware {
#throttleFor(module, action, sub) array?
#reject(retryAfter) void
}
class ApiCodes {
<<constants>>
}
Router --> ApiResolver : "解析路由"
ApiResolver --> UserAuthMiddleware : "中间件别名"
ApiResolver --> ThrottleMiddleware : "中间件别名"
UserAuthMiddleware --> ApiCodes : "错误码"
ThrottleMiddleware --> ApiCodes : "错误码"
图表来源
- Router.php:36-67
- ApiResolver.php:40-107
- UserAuthMiddleware.php:25-93
- ThrottleMiddleware.php:25-90
- ApiCodes.php:21-74
章节来源
- Router.php:28-67
- ApiResolver.php:30-107
- UserAuthMiddleware.php:25-93
- ThrottleMiddleware.php:25-90
- ApiCodes.php:21-74
性能考虑
- 路由匹配:基于声明式匹配器与方法过滤,命中失败快速返回 404/405,减少无效分支。
- 中间件顺序:安全头与代理信任前置,限流紧随其后,认证在后,尽早拦截非法与高频请求。
- 限流粒度:按 IP+路由键统计,避免全局阈值导致误伤;对高成本接口单独收紧配额。
- 响应体:统一 ApiResponse JSON,减少序列化开销与格式不一致问题。
- 缓存建议:对只读接口可结合缓存层(如 Redis)降低数据库压力;对高频读取的资源(如商品、文章)启用短 TTL 缓存。
- 连接与并发:在高并发场景下,建议配合反向代理(Nginx)与 PHP-FPM 调优,限制单进程最大请求数,避免内存泄漏累积。
故障排查指南
- 404 Not Found:检查 route 参数是否正确,确认 api/route/*.php 中已声明对应模块/动作。
- 405 Method Not Allowed:确认请求方法与路由声明一致(GET/POST 等)。
- 401 Unauthorized:检查 Authorization: Bearer 是否携带有效 token,确认 features.user 已开启且模块鉴权模式为 required。
- 403 Forbidden:确认工作端身份是否满足 work_required 要求。
- 429 Rate Limited:检查限流配额与窗口,必要时调整 ThrottleMiddleware 中的 limits 配置。
- 500 Server Error:查看入口未捕获异常处理逻辑,定位异常堆栈与日志。
章节来源
- Router.php:48-60
- UserAuthMiddleware.php:77-93
- ThrottleMiddleware.php:75-90
- index.php:40-71
结论
DouPHP 的 API 路由系统以声明式路由与中间件管道为核心,实现了清晰的 RESTful 风格、严格的鉴权与限流策略,并通过统一的错误码与响应格式保障前后端契约一致性。建议在新增模块时严格登记鉴权模式与限流配额,遵循资源路由规范,并结合缓存与反向代理提升整体性能与稳定性。
附录
API 文档自动生成与 Swagger 集成建议
- 现状:仓库中未发现内置 Swagger/OpenAPI 生成器或文档页面。
- 建议方案:
- 在控制器方法中添加注解(如 @Route、@Param、@Response),使用第三方工具(如 swagger-php)扫描生成 OpenAPI 规范。
- 将生成的 spec.json 部署至静态站点,并使用 Swagger UI 展示交互式文档。
- 在 CI 流程中校验 spec 变更,确保接口演进可追溯。
- 注意事项:保持注解与路由声明一致,避免文档与实际行为不一致。
接口测试工具使用建议
- 本地测试:使用 Postman 或 Insomnia 导入 OpenAPI spec,快速生成请求模板与断言。
- 自动化测试:结合 PHPUnit 或 Pest 编写端到端用例,覆盖鉴权、限流与异常分支。
- 压测:使用 wrk 或 k6 对关键接口进行压测,评估限流策略与系统瓶颈。
API 路由最佳实践
- 明确资源边界:每个模块聚焦单一资源域,避免跨域耦合。
- 动词语义清晰:GET 用于读取,POST 用于创建,PUT/PATCH 用于更新,DELETE 用于删除。
- 版本管理:通过路由前缀(/v1、/v2)或 Accept 头协商进行版本控制,逐步废弃旧版本。
- 鉴权最小化:仅对必要接口启用 required,公开接口使用 optional/public。
- 限流精细化:按 IP 与路由键配置配额,对高成本接口单独收紧。
- 错误码统一:使用 ApiCodes 常量,避免硬编码字符串。
错误码规范
- 成功:OK
- 业务规则违反:BUSINESS_RULE_VIOLATION(默认 422)
- 参数非法:INVALID_PARAMS(默认 422/400)
- 字段校验失败:VALIDATION_FAILED(默认 422)
- 未认证:UNAUTHORIZED(默认 401)
- 需登录:AUTH_REQUIRED(默认 401)
- 无权限:FORBIDDEN(默认 403)
- 资源不存在:NOT_FOUND(默认 404)
- 配额超限:QUOTA_EXCEEDED(默认 422/429)
- 限流:RATE_LIMITED(默认 429)
- 服务端错误:SERVER_ERROR(默认 500)
- AI 相关:AI_CONFIG_UNAVAILABLE、CHAT_NOT_FOUND、CHAT_CREATE_FAILED、CHAT_SAVE_FAILED
章节来源
- ApiCodes.php:21-74