关于 remote-api-footguns
面向 Kotlin 和 Compose Multiplatform 开发者的远程 API 排错技能,按客户端、解析、认证和实时协议等主题整理生产应用中的常见陷阱,并提供验证命令。
主要功能
- 01收录 17 个远程 API 陷阱
- 02按主题提供独立参考文档
- 03解释故障模式及成因
- 04提供代码验证命令
适用场景
- 01设计多平台 HTTP 客户端
- 02排查响应解析或远程写入问题
- 03调试 OAuth 回调与重连逻辑
- 04验证 WebSocket 会话握手
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ maxrave-dev/ kotlin-footguns --skill remote-api-footguns安装后在 Claude Code 中输入/remote-api-footguns确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/api-ok-but-ignored.mdborrowed-wire-protocol-discipline.mdcurl-logger-ktor-plugin.mdenum-normalize-over-legacy-data.mdktor-kmp-client-architecture.mdlogin-state-fans-out-to-settings.mdmonotonic-clock-offset-sync.mdnested-flag-settings-auto-disable.mdoauth-callback-not-through-nav.mdparallel-chunked-download.mdprotobuf-without-codegen-kmp.mdpublish-a-snapshot-on-taking-the-role.mdresponse-to-domain-flow.mdretry-needs-backoff-and-cap.mdstructural-defensive-parsing.mdunknown-not-a-valid-score.mdwebsocket-session-handshake-lifecycle.md详细介绍
远程 API 易踩陷阱
从一个生产级 Kotlin 和 Compose Multiplatform 应用中提炼出的 17 个陷阱,每个都整理在 references/ 下的一个简短文件中。每个文件都介绍可用模式、陷阱(实际中出错的具体方式及其原因),以及 验证方法部分,其中提供可在用户自己的代码树中运行的命令。
如何使用此索引。 将即将编写的代码或正在排查的症状与以下条目进行匹配:每个条目都注明了主题,以及应促使你查看该条目的症状。使用 Read 工具读取所有可能适用的文件,然后再提出代码或修复方案;每个文件都不到 150 行。如果验证命令中提到了源项目的路径,请替换为用户代码树中的对应路径。
交叉引用。 文件中若出现此处未列出的、用反引号括起的陷阱名称,该名称位于同级区域技能中:使用 glob ../*/references/<name>.md 打开它。
客户端、解析与响应处理
ktor-kmp-client-architecture— 多平台 HTTP 技术栈:通过一个 expect/actual 返回引擎,各集成基于它构建自己的客户端——一个用于 API 调用的插桩客户端,旁边配一个刻意保持精简的客户端用于批量下载;按格式注册内容协商;更改设置时重建客户端,而不是修改它。适用于在 Kotlin Multiplatform 模块中搭建网络功能、代理设置似乎只对部分请求生效,或大型文件下载缓慢且日志刷屏的情况。curl-logger-ktor-plugin— 一个客户端插件,可将每个传出的请求记录为一条可直接粘贴的 curl 命令——使用 POSIX 单引号,确保包含引号、美元符号或换行符的正文在 shell 中不变;整条命令通过一次日志调用输出;支持脱敏列表;读取正文时不会消耗只能读取一次的通道。适用于想在应用外重放失败请求、粘贴后日志中的命令无法运行,或复现错误时需要根据日志手动重建请求的情况。parallel-chunked-download— 将一个文件拆分成 N 个字节范围请求,通过精简的 HTTP 客户端并行发送;每个分块写入独立的临时文件,按顺序合并,并通过通道支持的 flow 报告进度——还会说明何时可以安全使用范围请求、分块应有多大,以及为什么失败时只重试一个分块而不是整个文件。适用于大型下载速度低于网络带宽、下载在中断后从头开始,或进度条停在即将完成的位置的情况。structural-defensive-parsing— 读取结构会变化的响应——根据数据载荷自身声明的标记对字段分类,而不是依据字段位置;将过滤映射视为数据丢失,并统计丢弃的数据;解析失败时拒绝用占位符替代;从稳定的一端解析复合字符串。适用于解析器在一种区域设置下正常、另一种下却无法工作,列表项比源数据显示的少,或某处出现了从未输入过的虚构值的情况。response-to-domain-flow— 远程响应经过的五个阶段——位于各集成独立服务模块中的传输模型、纯解析层、领域模型、结果封装,最后进行收集——并规定每种集成都应使用独立模块,以免某个来源出错影响其他来源;同时说明如何放置类型,避免传输类型泄漏到界面中。适用于添加第二个远程来源、UI 文件开始导入响应类,或响应结构发生变化后界面一直显示加载动画的情况。api-ok-but-ignored— 远程写入可能返回“ok”,却仍丢弃你发送的数据;它只会在随成功响应一同返回的次要字段中说明这一点。将“已接受但已丢弃”建模为独立结果;每次写入时都读取该字段,并对丢弃情况发出醒目日志。适用于每次提交都报告成功、但数据始终未出现在另一端的情况。unknown-not-a-valid-score— 解析失败时使用的回退值必须是合法取值范围之外的哨兵值,或由类型明确表达;绝不能使用成功路径也能产生的值。将“未知”作为独立状态公开。适用于字段的含义取决于其来源、占位符显示在界面上,或调用方无法区分缺失值与测量值的情况。enum-normalize-over-legacy-data— 读取远程来源自行声明的类型标记——每次比较前都进行规范化,因为旧版应用存储的本地行可能包含应用自创的标签;将 null 视为“来源未说明”,而不是默认值;公开 is-known 谓词,让调用方可以根据已知状态分支;通过写回方式修正旧行,而不是执行迁移。适用于存储的类型列包含多种拼写、某个条目被当成错误类型,或准备添加数据库迁移来修复历史值的情况。
身份验证、重试与账户状态
oauth-callback-not-through-nav— 将返回的身份验证回调令牌直接交给会话状态,并让登录界面通过观察已存储的会话自行关闭——通过导航传递令牌会推入第二个登录界面,而登录后的关闭操作会关闭错误的界面。适用于基于浏览器的登录成功,但用户仍停留在登录界面的情况。retry-needs-backoff-and-cap— 为每个重连循环设置指数退避、上限、不予重试的故障类别和生命周期门控——然后为该功能提供健康状态信号,因为悄无声息地失效的功能会持续故障数月。适用于后台连接耗尽电池、错误凭据导致无限重连,或集成悄然停止工作的情况。login-state-fans-out-to-settings— 必须在注销操作本身的关键节点重置所有依赖登录状态的设置——否则,受门控的开关会继续为你已无法通过身份验证的服务保持开启状态,并永远静默无操作,或在每个周期都报错。适用于功能开关卡在开启状态、无法关闭,或仍在使用已失效凭据运行的情况。nested-flag-settings-auto-disable— 受父条件约束的子开关必须根据父条件的当前值触发自动禁用效果;门控关闭时应将其置灰而非隐藏,并在使用该开关的地方再次进行门控——否则子开关会卡在开启状态,用户也无法将其清除。适用于设置开关卡在开启状态、显示已启用却呈灰色,或前置条件失效后仍继续生效的情况。
实时会话和线路协议
monotonic-clock-offset-sync— 根据 ping/pong 往返时间估算对端的时钟偏移量:先扣除对端自身的处理时间,再将结果减半;根据迄今为止观测到的最佳往返时间为每个样本加权;确保本地时间源单调递增;在估算值尚不可用时,回退到未经校正的值。当多个设备必须先对当前时间达成一致,才能对流的位置达成一致;当群组在拥塞网络中逐渐不同步;或当设备调整时钟后位置校正出现跳变时,请使用。protobuf-without-codegen-kmp— 在共享 Kotlin 代码中使用 protobuf:为普通数据类添加字段编号注解,无需生成代码层;同时包含让字节与生成的编码器输出一致的编码器设置、字节数组字段所需的相等性重写,以及确保等价性的符合性测试。当基于模式的协议必须支持每个目标平台而不只是 JVM;当编码缺失的嵌套字段时抛出异常;或当往返测试通过、实际对端却拒绝帧时,请使用。borrowed-wire-protocol-discipline— 实现他人定义的协议时应遵循的规则:不得重命名或重新排序;模式中省略的常量应从对端实现中读取,不要猜测;未知消息类型应解码为 null,而不是抛出异常;协商得到的功能只能缩减,不能扩大。当客户端必须与不受你控制的实现互操作;当连接已建立却无法继续;或当较新版本的对端导致会话中断时,请使用。websocket-session-handshake-lifecycle— WebSocket 会话的建立与拆除顺序:在发送第一条消息前启动读取器,因为响应会通过它返回;使用带超时的 deferred 完成握手;在不可取消的上下文中发送关闭帧;使用挂起而非丢弃事件的缓冲区。当套接字已连接但会话始终无法使用;当主动断开连接后,对端仍以为你在线;或当客户端在流量突增后失去同步时,请使用。publish-a-snapshot-on-taking-the-role— 共享会话中的每个发布者都由状态变更触发,因此,已经运行的参与者接手发布角色时不会发送任何内容,群组便会陷入沉默——成为源时发布完整快照,并在新成员加入时再次发布。当会话启动后一直为空,直到有人操作传输;新加入者看不到任何内容;或状态监听器看起来都正常、群组却仍一无所知时,请使用。
评论
支持 Markdown