前端开发
在后端 canister 集成外部 REST API 时…
适用于 Caffeine AI 的 Motoko 后端 canister 调用外部 REST API(GET/HEAD/POST/PUT/DELETE/PATCH),确保请求有服务端强制边界且响应契约经过验证。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
在后端 canister 集成外部 RE特定
解决思路
- 对每个外部 API 请求使用 provider 强制的有界请求:响应必须受 identifier、pagination、time range、geographic area、result count 或其他适合功能的服务端边界限制。
- 将每个响应限制为同时不超过 10_000 条和 1 MB;需要时再分页。
- 选择与功能匹配的边界;五种边界不可互换。按用户提供的单个实体查询(flight number、order id、ticker、postcode)时,只能使用 identifier bound;不要为了找该实体而分页遍历集合,分页是给用户主动翻页的列表用的,不是搜索。
- 把每个边界放进实际的 Motoko HTTP 请求中;只在本地测试里使用的边界不能保护 canister。
- 绝不要抓取无界集合并只在 canister 内过滤;预期响应大小、典型流量或当前数据量小都不是边界。
- 如果 provider 无法强制响应边界并提供所需数据,必须拒绝该 API 或收窄功能;不要实现已知不安全的 fallback。
- 在本地用 curl 测试实现:确保 1:1 curl 调用成功并返回应用消费的每个字段;Motoko 代码变化后重新做本地 curl 测试。
- 用 check_canister_api_compliance 检查边界;它探测 endpoint 并按限制测量响应,且运行在 deploy gate 后面,它拒绝的 endpoint 不能发布。
- 记住模块上限:defaultMaxResponseBytes 为 1 MB,check_canister_api_compliance 按 1 MB 和 10_000 条测量;但它在更早阶段拒绝:URL 无服务端边界时,只要探测响应超过字节上限四分之一或超过 1_000 条就阻止。
- 把上述危险区间视为危险:一次性 curl 可能通过,但之后增长到 canister 解析 payload 时超过每消息指令预算;按更严格边界设计,在服务端限制请求。
- 例如航班查询:不要请求 https://opensky-network.org/api/states/all(全球所有飞行器,约 10-13k 行)再在 Motoko 中扫描 callsign;这会因 IC0522 超过单消息 40000000000 指令限制而被拒绝,缩小题分页也无助于避免遍历整个集合。
- 对同一 endpoint 使用 provider 已提供的正确边界,如 ?icao24=<hex> identifier bound,返回千字节级、一架飞行器、一条记录可解析。
- 在后端使用现有模块 mo:caffeineai-http-outcalls/outcall.mo;它提供适用于 IC 支持的每种 HTTP 方法的通用有界请求函数,以及向后兼容的 GET 和 POST helper。
- 当需要状态码、headers、自定义响应限制,或 GET/POST 以外的方法时,使用 httpRequest;maxResponseBytes 可设置更低限制,模块将所有请求封顶在 defaultMaxResponseBytes(1 MB)。
- 模块以 is_replicated = ?false 执行每个 HTTP outcall;调用方不能启用 replicated execution。
- 简单 GET 使用向后兼容 helper,例如 OutCall.httpGetRequest(url, [], transform) 最短路径。
- 按示例定义 query transform:public query func transform(input: OutCall.TransformationInput) : async OutCall.TransformationOutput { OutCall.transform(input) },并在请求中传入 transform。
- 通过 OutCall.httpRequest 构造请求时,提供 url、method、headers、body、maxResponseBytes 和 transform;POST 使用 httpPostRequest 类似。
- 在认为 HTTP outcall 完成前,必须用 curl 在本地执行等价请求;不要只依赖记住的 API 文档或 Motoko 编译通过。以下检查全部必需;任一失败则 outcall 未完成且不得部署。
- 用 curl 测试 Motoko 中实现的精确请求:相同 HTTP method、API version、endpoint path、query parameters、headers、body;测试相关 endpoint 或添加实现未使用的参数都不算有效验证。
- 追踪一个代表性用户输入端到端经过每次转换成 API 请求,然后测试最终得到的精确请求;例如用户输入一种 identifier 而 provider 期望另一种格式时,要端到端验证映射;只调用 provider 的 base 或 listing endpoint 不够。
- 验证消费的响应契约:运行 curl --fail-with-body --silent --show-error,验证成功状态码以及应用消费的每个响应字段和类型;仅 JSON 合法不够。
- 对实现使用的精确 URL 和 method 运行 check_canister_api_compliance;它测量响应是否满足 outcall 字节上限和条目边界,并报告 URL 是否有服务端边界,且在 deploy gate 后机械执行,未通过的 host 不能发布。
- 当 check_canister_api_compliance 拒绝 endpoint 时,选择兼容的公共 API 或诚实收窄功能;不要实现无界 fetch-all 再在 canister 内过滤。
- 响应边界是 check_canister_api_compliance 的职责,不是 curl 的;上述 curl 检查负责它做不到的事:它探测 endpoint 而非应用,不知道应用读取哪些响应字段,也不知道什么用户输入生成了 URL。
- 如果请求失败或任一项检查未满足,检查状态码和响应体;用 web search 查看 provider 当前官方 API 文档和 release/migration notes,确认当前 API version、endpoint、parameter 名称/格式、required headers、request body;不要猜测。
- 修复 Motoko 请求以匹配可工作的 REST 请求并重新运行 curl;重复直到所有检查通过,然后重新运行 backend checks。任何必需检查缺失或失败时绝不报告完成。
- 根据典型失败线索排查:400 表示参数或 body 形状无效;404/410 通常表示 endpoint 或 API version 过时;405 表示 method 错误;415 表示 content type 错误;429 和 5xx 只有在对照当前官方文档确认请求后才视为 quota 或 provider availability 问题。
适用边界 · 注意事项
- 不适用于前端发起的 HTTP 请求;本技能只覆盖 backend canister。
- 不适用于不依赖 Caffeine AI / Internet Computer Motoko canister 与 mo:caffeineai-http-outcalls 模块的项目。
- 外部 API 无法提供任何服务端强制边界且无法收窄功能时不要使用;应拒绝该 API,而不是实现无界抓取后过滤。