You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

已配置.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 });
    }
  }
});

关键修正点

  1. 把node-fetch的动态导入移到循环外,避免每次循环都加载模块,减少不必要的异步操作。
  2. 重构循环逻辑:原来的代码在第一次成功请求后就直接发送响应并return,现在改成累计成功创建的数量,等所有循环执行完再统一发送响应,避免中途重复发送。
  3. 加了参数合法性校验,提前拦截无效请求,避免后续无意义的API调用。
  4. 在catch块里加了res.headersSent判断,防止已经发送过响应后再次发送。

额外提醒

  • 循环调用外部API的时候,最好加个间隔(比如每次循环后await new Promise(resolve => setTimeout(resolve, 1000))),别太频繁,容易触发服务商的频率限制。
  • 给createNew函数也加个错误处理,确保数据库操作出问题时能被正确捕获。

内容的提问来源于stack exchange,提问作者fay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 04:01:03