已配置.env,如何解决调用带API Key/Secret的外部API的两类报错?
问题解决方案
一、先搞定「Invalid Key」认证错误
这说明你的API密钥没通过服务商的校验,按下面步骤排查:
- 核对.env文件里的
API_KEY和API_SECRET,必须和服务商提供的密钥完全一致,别多打空格、别加多余引号,确保是纯文本格式。 - 在代码最开头加两行日志,确认环境变量是否真的加载到了:
如果输出是console.log("加载的API_KEY:", apiKey); console.log("加载的API_SECRET:", apiSecret);undefined,说明你没配置dotenv,得先装包然后在代码最顶部加:require('dotenv').config(); - 手动验证Basic Auth的编码是否正确:把正确的密钥对用
Buffer.from("你的API_KEY:你的API_SECRET").toString("base64")生成字符串,和代码里Authorization头的内容对比,确保一模一样。
二、修复「Cannot set headers after they are sent to the client」错误
这个错是因为同一个HTTP请求里,你尝试发送多次响应,你的代码有两个潜在问题,改成这样就能解决:
修正后的代码
const apiKey = process.env.API_KEY; const apiSecret = process.env.API_SECRET; // 把fetch的导入移到循环外面,别每次循环都加载一遍 const fetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args)); app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.get("/insert/data/:start", async (req, res) => { let start = parseInt(req.params.start); // 先校验参数是否合法,不合法直接返回错误 if (isNaN(start) || start < 1) { return res.status(400).send({ error: "start参数不合法" }); } try { let createdCount = 0; while (start <= 3) { const response = await fetch( `https://data.co/api/docs/v1?a_id=${start}`, { headers: { Authorization: `Basic ${Buffer.from( `${apiKey}:${apiSecret}` ).toString("base64")}`, }, } ); if (response.ok) { const data = await response.json(); console.log(data); await createNew(data.jsonData); createdCount++; start++; // 递增start,继续下一次循环 } else { const errorData = await response.json(); throw new Error( `拉取数据失败。API错误信息: ${JSON.stringify(errorData)}` ); } } // 所有循环执行完,统一发送成功响应 res.send({ Created: createdCount }); } catch (error) { // 确保只发送一次错误响应,避免重复发送 if (!res.headersSent) { res.status(500).send({ error: error.message }); } } });
关键修正点
- 把
node-fetch的动态导入移到循环外,避免每次循环都加载模块,减少不必要的异步操作。 - 重构循环逻辑:原来的代码在第一次成功请求后就直接发送响应并return,现在改成累计成功创建的数量,等所有循环执行完再统一发送响应,避免中途重复发送。
- 加了参数合法性校验,提前拦截无效请求,避免后续无意义的API调用。
- 在catch块里加了
res.headersSent判断,防止已经发送过响应后再次发送。
额外提醒
- 循环调用外部API的时候,最好加个间隔(比如每次循环后
await new Promise(resolve => setTimeout(resolve, 1000))),别太频繁,容易触发服务商的频率限制。 - 给
createNew函数也加个错误处理,确保数据库操作出问题时能被正确捕获。
内容的提问来源于stack exchange,提问作者fay
相关产品推荐
相关产品推荐

