简介
本技术文档面向DouPHP小程序与后端主站的API集成架构,聚焦以下目标:
- 统一HTTP请求封装、响应信封解析、错误处理与重试策略
- 统一的API调用方式:请求拦截器、响应拦截器、认证令牌管理
- 数据缓存策略:内存缓存、TTL过期、强制刷新、去重
- API版本管理与兼容性策略
- 安全与性能优化建议:限流、连接复用、批量合并等
项目结构
本项目采用“前后端分离”的模块化组织:
- 小程序前端位于 miniprogram/default,提供统一的HTTP服务层、全局应用初始化、状态存储等
- 后端API入口位于 api,包含路由、中间件、控制器、门面(鉴权)与初始化流程
- 公共能力位于 core,如HTTP响应封装、异常处理、配置与容器等
graph TB
subgraph "小程序"
MP_APP["app.ts<br/>全局初始化"]
HTTP["http.ts<br/>统一HTTP层"]
STORES["stores/*<br/>状态持久化"]
end
subgraph "后端API"
ENTRY["api/index.php<br/>入口与异常兜底"]
INIT["api/init/Init.php<br/>启动装配"]
MW_AUTH["UserAuthMiddleware.php<br/>认证中间件"]
MW_THROTTLE["ThrottleMiddleware.php<br/>限流中间件"]
MW_SEC["SecurityHeadersMiddleware.php<br/>安全头"]
FACADE_AUTH["api/facade/Auth.php<br/>Token鉴权"]
ROUTE_INDEX["api/route/index.php<br/>示例路由"]
CTRL_BASE["api/controller/BaseController.php<br/>控制器基类"]
end
MP_APP --> HTTP
HTTP --> |Bearer Token| MW_AUTH
HTTP --> |JSON信封| ENTRY
ENTRY --> INIT
INIT --> MW_AUTH
INIT --> MW_THROTTLE
INIT --> MW_SEC
MW_AUTH --> FACADE_AUTH
ROUTE_INDEX --> CTRL_BASE
核心组件
- 小程序统一HTTP层:负责请求封装、标准信封解析、拦截器、内存缓存与去重、调试增强
- 后端API入口与初始化:统一异常兜底、站点关闭检测、语言与模块加载、Guard注册
- 认证中间件与门面:从Authorization头提取token并解析用户上下文,注入到当前请求
- 限流与安全头:对敏感接口按IP限流,统一设置安全响应头
- 路由与控制器:声明式路由映射到控制器方法,控制器基类提供API专属能力
架构总览
小程序通过统一HTTP层发起请求,携带Bearer Token;后端API入口进行异常兜底与路由分发,中间件链完成安全头、限流与认证;认证中间件调用鉴权门面解析token并注入用户上下文;控制器返回标准JSON信封;小程序侧解析信封并触发拦截器。
sequenceDiagram
participant MP as "小程序"
participant HTTP as "http.ts"
participant API as "api/index.php"
participant INIT as "api/init/Init.php"
participant MW as "UserAuthMiddleware.php"
participant AUTH as "api/facade/Auth.php"
participant CTRL as "控制器"
MP->>HTTP : get/post(url, data, opts)
HTTP->>HTTP : 注入默认头(含Authorization)
HTTP->>HTTP : 检查内存缓存/去重
HTTP->>API : wx.request(...)
API->>INIT : boot() 启动装配
INIT->>MW : 执行认证中间件
MW->>AUTH : resolveUserContext(token)
AUTH-->>MW : {ok, userId, userProfile, work}
MW-->>API : 注入auth('api')上下文
API->>CTRL : 路由到具体业务
CTRL-->>API : 返回标准信封{code,message,data,...}
API-->>HTTP : JSON响应
HTTP->>HTTP : 解析信封/成功或失败拦截
HTTP-->>MP : Promise(data) 或 ApiError
详细组件分析
小程序统一HTTP层
- 请求封装:统一Content-Type与Authorization头,支持GET/POST/PUT/DELETE(PUT/DELETE通过_method伪装)
- 响应信封:严格解析{code,message,data,errors,request_id},code为'OK'视为成功
- 拦截器:onRequest/onSuccess/onError,支持全局错误处理(如UNAUTHORIZED登出)
- 缓存与去重:内存缓存+TTL,相同GET在飞行中复用Promise
- 调试:request_id追踪,调试环境弹出服务端异常堆栈
flowchart TD
Start(["进入 request(config, opts)"]) --> BuildCfg["构建默认配置<br/>Content-Type / Authorization"]
BuildCfg --> RunReqIntc["执行请求拦截器"]
RunReqIntc --> CacheCheck{"启用缓存且未强制刷新?"}
CacheCheck --> |是| HitCache{"命中且未过期?"}
HitCache --> |是| ReturnCache["直接返回内存缓存"]
HitCache --> |否| DoNet["发起网络请求"]
CacheCheck --> |否| DoNet
DoNet --> Dedupe{"GET且开启去重?"}
Dedupe --> |是| Inflight["复用inflight Promise"]
Dedupe --> |否| WxReq["wx.request"]
WxReq --> ParseEnv["解析标准信封"]
ParseEnv --> Ok{"code === 'OK' ?"}
Ok --> |是| SuccessIntc["执行成功拦截器"] --> Resolve["resolve(data)"]
Ok --> |否| ErrorIntc["执行错误拦截器"] --> Reject["reject(ApiError)"]
ReturnCache --> End(["结束"])
Resolve --> End
Reject --> End
后端API入口与初始化
- 入口职责:设置路由委托、抽取route参数、启动Init、分发路由、统一异常兜底(业务异常、未捕获异常)
- 初始化职责:定义IS_API/IS_MINIPROGRAM常量、实例化核心对象、加载语言与模块、注册Guard、检查站点关闭
- 安全与限流:中间件链由Init装配,统一输出JSON
sequenceDiagram
participant Entry as "api/index.php"
participant Init as "api/init/Init.php"
participant Route as "Router"
participant MW as "中间件链"
Entry->>Entry : 设置路由委托
Entry->>Entry : 抽取route参数
Entry->>Init : boot()
Init->>Init : 定义常量/实例化核心/加载语言与模块
Init->>MW : 注册安全头/限流/认证
Entry->>Route : dispatch()
Route-->>Entry : Response
Entry->>Entry : send()/exit
Entry->>Entry : 捕获异常并返回JSON
认证中间件与鉴权门面
- 中间件:从Authorization头读取Bearer token,调用auth('api')->resolveUserContext()解析上下文,注入auth('api')
- 鉴权门面:校验token有效性,构建轻量用户资料与工作端信息,供后续业务使用
- 拒绝策略:未登录返回401,无工作端身份返回403
classDiagram
class UserAuthMiddleware {
+configFile() string
+resolveContext() array
+inject(context) void
+hasWorkIdentity() bool
+rejectUnauthenticated() void
+rejectForbidden() void
}
class Auth {
+id() int
+user() array
+check() bool
+guest() bool
+workId() int
+work() array
+hydrate(context) void
+reset() void
+checkLoginState(token) array
+resolveUserContext(token) array
}
UserAuthMiddleware --> Auth : "调用 resolveUserContext/hydrate"
限流与安全头
- 限流中间件:针对登录、注册、短信验证码、匿名写接口、防伪查询、LLM成本端点等按IP限流,超限返回429并附带Retry-After
- 安全头中间件:统一设置安全响应头(继承抽象基类行为)
路由与控制器
- 路由:声明式路由将/api/?route=xxx映射到控制器方法
- 控制器基类:提供API端专属能力(如会员中心导航),所有API控制器继承该基类
依赖关系分析
- 小程序HTTP层依赖微信原生wx.request,并通过拦截器扩展功能
- 后端API入口依赖路由与中间件链,中间件依赖鉴权门面
- 鉴权门面依赖数据库与用户服务以构建用户上下文
- 控制器依赖基础框架能力(DB、语言、路由等)
graph LR
HTTP["http.ts"] --> WX["wx.request"]
HTTP --> API_ENTRY["api/index.php"]
API_ENTRY --> INIT["api/init/Init.php"]
INIT --> MW_AUTH["UserAuthMiddleware.php"]
MW_AUTH --> AUTH["api/facade/Auth.php"]
AUTH --> DB["数据库/用户服务"]
API_ENTRY --> ROUTE["路由"]
ROUTE --> CTRL["控制器"]
性能考虑
- 请求去重:相同GET请求在飞行中复用Promise,减少重复网络开销
- 内存缓存:GET请求可启用内存缓存与TTL,避免频繁网络请求
- 强制刷新:revalidate=true时绕过缓存,用于SWR场景
- 限流保护:对高频敏感接口按IP限流,防止滥用
- 连接复用:小程序wx.request底层复用连接,合理合并请求可减少握手开销
- 批量处理:对同一资源的多次读操作可通过缓存与去重降低负载
- 调试与监控:利用request_id关联前后端日志,便于定位问题
故障排查指南
- 未捕获异常:API入口统一捕获并返回JSON 500,调试模式可输出详细堆栈
- 认证失败:中间件返回401/403,小程序侧通过onError拦截器统一处理(如登出)
- 限流触发:返回429并附带Retry-After,客户端应遵循退避策略
- 信封解析失败:统一包装为ApiError,包含code/message/errors/request_id,便于追踪
- 调试工具:调试环境自动开启vConsole,并在错误消息附加request_id片段
结论
本架构通过小程序统一HTTP层与后端API中间件链实现了标准化的数据交互:
- 统一信封与拦截器机制确保前后端契约一致
- 认证与限流保障安全性与稳定性
- 内存缓存与去重提升性能
- 调试与监控能力便于问题定位 建议在后续迭代中继续完善版本管理与兼容性策略,并引入更细粒度的缓存失效与批量处理能力。
附录
数据缓存策略
- 本地缓存:小程序内存缓存(memoryCache)+ TTL过期控制
- 网络缓存:通过revalidate实现SWR(Stale-While-Revalidate)
- 失效机制:按key前缀清理或全部清空,结合业务事件触发
API版本管理与兼容性
- 版本标识:可在URL路径或请求头中引入version字段,后端根据版本路由至不同控制器或兼容逻辑
- 兼容策略:后端保持向后兼容,废弃字段标记并保留解析逻辑,逐步迁移
- 客户端适配:通过拦截器动态注入版本信息,并根据响应中的版本提示升级
安全考虑
- 传输安全:HTTPS强制,设置安全响应头(CSP、X-Frame-Options等)
- 认证安全:Bearer Token仅通过Authorization头传递,服务端校验token有效性
- 限流防护:对敏感接口按IP限流,防止暴力破解与滥用
- 输入校验:控制器与服务层进行参数校验,避免注入与越权
性能优化建议
- 请求合并:对同一资源的多次读操作合并为一次请求(结合缓存与去重)
- 批量处理:对写操作进行批量提交,减少网络往返
- 连接池:小程序wx.request底层复用连接,合理控制并发
- 缓存策略:合理使用内存缓存与TTL,避免冷数据占用内存