后端与接口
在 Caffeine/ICP canister 中读取…
当需要从 canister 获取天气、预报、天文、时区、IP 定位或地点搜索数据时,使用 weatherapi-client mops 包通过出站 HTTPS 调用 WeatherAPI.com。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
在 Caffeine/ICP canis特定
解决思路
- 安装并使用 weatherapi-client mops 包(~0.2.0),不要手写 ic.http_request 调用 api.weatherapi.com,因为手写会绕过非复制出站调用保护、生成的 JSON 解码和 API key 处理。
- 从 mo:weatherapi-client/Apis/APIsApi 导入所需函数(如 realtimeWeather、forecastWeather),从 mo:weatherapi-client/Config 导入 Config 和 defaultConfig。
- 用 { defaultConfig with auth = ?#apiKey apiKey } 构造配置,API key 存放在由管理员调用写入的 stable 变量中,绝不硬编码在源码里。
- 在 weatherapi.com 注册获取 API key;免费层覆盖 current、3 天预报、astronomy、timezone、search 和 IP lookup,history、future、marine 和 14 天预报需要付费计划,免费 key 返回 403。
- 注意客户端把 key 作为 ?key=… 追加到 URL(WeatherAPI 不接受 Authorization 头),所以 key 会出现在请求 URL 中,不要记录构建出的 URL。
- 保持 is_replicated = ?false(defaultConfig 默认值),这是正确性要求:每个响应携带逐请求时钟(Location.localtime/localtime_epoch、Current.last_updated/last_updated_epoch),复制出站调用要求各节点响应逐位相同会破坏共识并多消耗约 13 倍 cycles。
- 仅在配合能剥离易变字段的 transform 时才覆盖为 is_replicated = ?true。
- 使用九个操作之一:realtimeWeather(cfg, q, lang) 对应 /current.json;forecastWeather(cfg, q, days, dt, unixdt, hour, lang, alerts, aqi, tp) 对应 /forecast.json;historyWeather(cfg, q, dt, unixdt, endDt, unixendDt, hour, lang) 对应 /history.json;futureWeather(cfg, q, dt, lang) 对应 /future.json;marineWeather(cfg, q, days, dt, unixdt, hour, lang) 对应 /marine.json;astronomy(cfg, q, dt) 对应 /astronomy.json;timeZone(cfg, q) 对应 /timezone.json;ipLookup(cfg, q) 对应 /ip.json;searchAutocompleteWeather(cfg, q) 对应 /search.json。
- days 参数是枚举而非数字:ForecastWeatherDaysParameter 为 #_1_ 到 #_14_,MarineWeatherDaysParameter 为 #_1_ 到 #_7_,注意下划线转义写法(#_3_ 而非 #_3 或 3)。
- q 参数可传任意 WeatherAPI 位置查询:"Zurich"、"47.37,8.55"、邮编、IATA 代码或 "auto:ip"。
- 所有响应字段都是可选的(WeatherAPI 不标记必填字段),用 do ? 块(如 do ? { res.current!.temp_c! })穿透访问,而不是嵌套 switch,并自行决定字段缺失对调用方的含义。
- 可选查询参数传 "" 或 0 表示省略(WeatherAPI 拒绝空 lang= 和零值数值),没有 ?Text 参数可留 null。
- 注意 hour = 0 不会选择午夜,而是完全省略 hour 过滤并返回全天小时数组;如需 00:00 需自行过滤返回的 hour : ?[ForecastForecastdayInnerHourInner]。
- 用 try/catch 捕获错误并展示 Error.message(err);非 2xx 响应和解码失败会 throw Error.reject(…),消息格式为 HTTP <status> body[<n>B]=<first 100 chars>: <reason>,足以区分 401(key 错误)、403(端点不在计划内)和 400(q 无法解析)。
适用边界 · 注意事项
- 不要手写 ic.http_request 调用 api.weatherapi.com,这是被禁止的反模式。
- 不要在未配合剥离易变字段的 transform 时设置 is_replicated = ?true。
- 不要在源码中硬编码 API key 或记录包含 key 的构建 URL。