现场是这样的。把提交逻辑放进 Cloudflare Worker,用 fetch 转发到 api.indexnow.org,本地 wrangler 测试正常,线上返回 401,Worker 日志里请求体是空的。用 curl 直连同样的 payload 能成功,密钥确认存在环境变量里。
中间走过弯路,把「密钥存在 Worker 环境变量里但只绑了预览环境」当成主因,改完现象没变。
真正麻烦的地方在于,几个原因的现象几乎一样。Worker 没有把 Content-Type 透传 上游按表单去解析;请求体是 ReadableStream 只能读一次 重试时已经消费完;host 字段用了 workers.dev 而不是站点主域。
上来先打开 Worker 的实时日志看请求体
wrangler tail --format pretty
显式设置头并重新序列化 body
await fetch(u, {method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(payload)})
然后核对生产环境变量绑定
wrangler secret list --env production
等前面都确认过,再用同样的 payload 走 curl 对比返回码
curl -s -o /dev/null -w '%{http_code}\n' -X POST https://api.indexnow.org/indexnow -H 'Content-Type: application/json' -d @payload.json
怎么算真的好了,看的是同一批现象。Worker 返回 200 且上游响应体里带 requestId,Bing 日志出现对应 URL 的抓取。
容易忽略的是,边缘函数里请求体只能消费一次,重试逻辑要在发请求前重新构造 payload。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。
