创建谷歌Calendar Watch通道后,接收Webhook时未收到头部数据
解决谷歌Calendar Webhook推送头部无数据的问题
嘿,我之前折腾谷歌Calendar Webhook的时候也碰到过类似的坑,咱们一步步来排查和解决:
首先,先确认你有没有处理谷歌的通道验证请求
这是最容易被忽略的关键节点!当你调用events.watch创建通道后,谷歌会立刻给你的Webhook地址发一个GET验证请求,里面携带hub.mode、hub.challenge、hub.topic这些参数。如果你的端点没正确响应这个请求,谷歌会判定你的地址无效,不会激活通道,自然后续也不会推送任何事件(或者推送你也收不到正确的头部)。
处理验证请求的示例代码(以Rails控制器为例):
def notifications if request.get? # 必须返回hub.challenge的值作为响应体,状态码保持200 render plain: params[:hub_challenge], status: 200 else # 这里处理实际的推送事件,先打印所有头部排查数据 request.headers.each do |key, value| puts "#{key}: #{value}" end render plain: "OK", status: 200 end end
检查你的通道创建代码的几个关键参数
看你的代码,有几个细节需要确认:
client = Google::APIClient.new client.authorization.access_token = "#{access_token}" service = client.discovered_api('calendar', 'v3') data = client.execute( api_method: service.events.watch, parameters: { calendarId: "primary" }, body_object: { id: "34234234-89ab-cdef-0123456789ab", # 这个ID必须全局唯一,每个通道不能重复 type: "web_hook", # 注意是下划线格式,别写成webhook或者WebHook address: "#{my_domain}/notifications" # 非本地测试环境必须用HTTPS!谷歌不接受HTTP地址 # 可选但建议添加:token: "your_custom_verification_token" # 这个token会在推送请求的X-Goog-Channel-Token头部返回,用来验证请求来源 } )
- HTTPS要求:如果你的
my_domain是公网地址,必须用HTTPS,否则谷歌不会发送推送请求。本地测试可以用ngrok生成临时HTTPS地址。 - 通道ID唯一性:每个
watch请求的id必须唯一,重复的ID会覆盖之前的通道,导致推送异常。
确认授权的Scope是否足够
你的access_token对应的授权Scope必须包含日历事件的权限,比如:
https://www.googleapis.com/auth/calendar.events(仅事件操作权限)- 或者更宽泛的
https://www.googleapis.com/auth/calendar(全日历权限)
如果Scope不够,创建的通道可能无效,谷歌不会推送事件。
检查服务器/代理是否过滤了请求头部
如果你用了Nginx之类的反向代理,要确保它没有过滤掉谷歌推送的自定义头部。谷歌推送的关键头部包括:
X-Goog-Resource-StateX-Goog-Message-NumberX-Goog-Channel-IDX-Goog-Channel-Token
比如Nginx里要确保转发所有原始头部,不要配置过滤规则:
proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 不要添加移除自定义头部的配置
调试小技巧
用ngrok把本地服务暴露到公网,然后在ngrok的控制面板里查看所有请求的详情,包括头部和请求体,这样就能直接确认谷歌到底有没有发送头部,或者是不是你的服务没正确接收。
内容的提问来源于stack exchange,提问作者Mayank
相关产品推荐
相关产品推荐

