You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Node.js中通过Axios或node-fetch调用API时配置代理与SSL证书

代理+SSL证书场景下Axios/Node-fetch调用API的问题排查与解决方案

嘿,来帮你排查下用Axios和node-fetch通过代理+SSL证书调用API失败的问题。看了你给出的代码,有几个关键地方需要调整,同时我也会提供node-fetch的配置方案供你参考。

一、Axios代码的潜在问题修正

你的Axios实现有几个细节需要调整,可能是导致请求失败的原因:

1. 代理变量未定义

代码里直接使用了proxy.hostnameproxy.port,但没看到这个变量的声明——这会直接导致报错。首先要确保proxy指向正确的代理地址和端口,比如从环境变量或配置文件获取:

const proxy = {
  hostname: process.env.PROXY_HOST, // 替换为你的代理主机
  port: process.env.PROXY_PORT     // 替换为你的代理端口
};

2. SSL配置的矛盾点

你同时设置了rejectUnauthorized: false(跳过证书验证)和ca: sslInfo.ca(传入自定义CA证书),这两个配置是冲突的:

  • 如果目标接口需要信任自定义CA签发的证书,应该把rejectUnauthorized设为true(默认值),确保sslInfo.ca是正确的PEM格式证书字符串/Buffer;
  • 如果只是临时跳过验证(不推荐生产环境使用),可以去掉ca配置,只保留rejectUnauthorized: false

另外,如果代理或目标服务器要求客户端证书认证,还需要补充certkey配置:

let httpsAgent = new HttpsProxyAgent({
  host: proxy.hostname,
  port: proxy.port,
  rejectUnauthorized: true,
  ca: sslInfo.ca,
  cert: sslInfo.cert, // 客户端证书(如果需要)
  key: sslInfo.key    // 客户端私钥(如果需要)
});

3. 冗余请求头清理

Access-Control-Allow-Origin响应头,不是请求头,放在请求headers里完全无效,直接删掉即可。

4. 错误捕获与调试

当前代码没有处理错误,建议添加错误捕获逻辑,方便定位问题:

.catch(err => {
  console.error('请求失败原因:', err.message);
  console.error('错误详情:', err.response?.data || err.stack);
  throw err; // 或根据业务需求处理错误
});

二、修正后的Axios完整代码

import axios from "axios";
import { getPrefetchedSSLConfig } from "./get-ssl-certs";
import HttpsProxyAgent from "https-proxy-agent";

// 定义代理配置
const proxy = {
  hostname: process.env.PROXY_HOST,
  port: process.env.PROXY_PORT
};

const callEndPoint = async () => {
  try {
    axios.defaults.baseURL = "https://api.endpoint.com";
    const sslInfo = getPrefetchedSSLConfig();
    
    const httpsAgent = new HttpsProxyAgent({
      host: proxy.hostname,
      port: proxy.port,
      rejectUnauthorized: true,
      ca: sslInfo.ca,
      // 如需客户端证书,取消下面注释
      // cert: sslInfo.cert,
      // key: sslInfo.key
    });

    const res = await axios({
      proxy: false, // 禁用Axios自带代理,由HttpsProxyAgent接管
      method: "GET",
      url: `/v1/api/endpoint`,
      responseType: "json",
      headers: {
        "Content-Type": "application/json",
        Accept: "application/json"
      },
      httpsAgent
    });

    return {
      data: res.data,
      status: res.status
    };
  } catch (err) {
    console.error('API调用失败:', err.message);
    console.error('错误详情:', err.response?.data || err.stack);
    throw err;
  }
};

export default callEndPoint;

三、Node-fetch的配置方案

如果你想用node-fetch实现相同逻辑,参考下面的代码:

import fetch from "node-fetch";
import { getPrefetchedSSLConfig } from "./get-ssl-certs";
import HttpsProxyAgent from "https-proxy-agent";

const proxy = {
  hostname: process.env.PROXY_HOST,
  port: process.env.PROXY_PORT
};

const callEndPoint = async () => {
  try {
    const sslInfo = getPrefetchedSSLConfig();
    const agent = new HttpsProxyAgent({
      host: proxy.hostname,
      port: proxy.port,
      rejectUnauthorized: true,
      ca: sslInfo.ca,
      // cert: sslInfo.cert,
      // key: sslInfo.key
    });

    const res = await fetch("https://api.endpoint.com/v1/api/endpoint", {
      method: "GET",
      headers: {
        "Content-Type": "application/json",
        Accept: "application/json"
      },
      agent // 绑定代理agent
    });

    if (!res.ok) {
      throw new Error(`HTTP错误状态: ${res.status}`);
    }

    const data = await res.json();
    return { data, status: res.status };
  } catch (err) {
    console.error('请求失败:', err.message);
    throw err;
  }
};

export default callEndPoint;

四、额外调试建议

  • 检查代理服务器是否支持HTTPS请求:如果代理只支持HTTP,需要改用HttpProxyAgent
  • 确认CA证书有效性:可以尝试用PEM字符串直接替换sslInfo.ca测试,排除证书读取问题;
  • 代理认证:如果代理需要用户名密码,在HttpsProxyAgent配置中添加auth: 'username:password'
  • 用curl测试连通性:
    curl -x http://proxy-host:proxy-port --cacert ./ca-cert.pem https://api.endpoint.com/v1/api/endpoint
    
    如果curl能成功,说明代码配置有问题;如果curl也失败,可能是网络或证书本身的问题。

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

火山引擎 最新活动