AWS Lambda中Alexa技能调用Todoist的HTTP Post请求失败排查
问题分析与解决方案
先拆解你遇到的两个核心问题,咱们一步步来解决:
1. 报错 hostHeader.replace is not a function 的根源
这个错误直接指向你代码里的options.hostname设置——你用了数组形式定义hostname,但Node.js的https.request方法要求hostname必须是字符串类型。当你传入数组时,内部处理host header的逻辑会尝试调用replace方法,而数组并没有这个原生方法,所以抛出了这个错误。
快速修复:把hostname改成字符串格式,比如:
const options = { hostname: 'api.todoist.com', // 这里用字符串,不是数组 path: '/rest/v2/tasks', method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_TODOIST_TOKEN' } };
2. 函数移入handler后请求不生效的问题
你把postZip放到exports.handler里后技能能正常运行,但Todoist没收到任务,结合Postman测试有效的情况,大概率是Lambda的异步执行逻辑没处理到位,再加上可能的请求细节遗漏:
(1)Lambda提前终止进程
Lambda是事件驱动的执行环境,如果你的postZip用的是回调式的https.request,但handler没有等待这个异步操作完成就返回了,Lambda会直接终止进程,导致请求还没发送完成就被中断了。
解决办法:把postZip改成返回Promise的形式,然后在handler里用async/await等待它执行完毕:
exports.handler = async (event) => { // 其他Alexa技能逻辑... const postZip = () => { return new Promise((resolve, reject) => { const req = https.request(options, (res) => { let data = ''; res.on('data', (chunk) => { data += chunk; }); res.on('end', () => { if (res.statusCode >= 200 && res.statusCode < 300) { resolve(JSON.parse(data)); } else { reject(new Error(`请求失败,状态码:${res.statusCode},响应内容:${data}`)); } }); }); req.on('error', (err) => { reject(err); }); // 注意:请求体必须是JSON序列化后的字符串,不能直接传对象 req.write(JSON.stringify({ content: '你的任务内容', project_id: '你的Todoist项目ID' })); req.end(); }); }; try { await postZip(); return { version: '1.0', response: { outputSpeech: { type: 'PlainText', text: '任务已成功添加到Todoist!' } } }; } catch (err) { console.error('添加任务出错:', err); return { version: '1.0', response: { outputSpeech: { type: 'PlainText', text: '添加任务失败,请稍后重试。' } } }; } };
(2)请求细节自查
虽然Postman能用,但代码里可能还有容易忽略的点:
- 确认
Authorizationheader里的token格式正确,必须是Bearer 你的Todoist令牌,没有拼写错误; - 检查请求体里的必填字段(比如
content、project_id)是否正确填写; - 打开Lambda的CloudWatch日志,查看请求的具体错误信息(比如响应状态码、错误内容),这能帮你快速定位问题。
内容的提问来源于stack exchange,提问作者Jack Flyer
相关产品推荐
相关产品推荐

