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

使用node-fetch请求HTTPS站点时遭遇HTTP协议不支持错误

node-fetch请求HTTPS站点触发HTTP协议错误的排查方案

问题描述

我用node-fetch抓取页面时遇到异常错误:明明请求的是HTTPS站点,却收到ERR_INVALID_PROTOCOL错误,提示“Protocol "http:" not supported. Expected "https:"”。这个问题只在特定URL(比如https://robinhood.com/l/privacy)出现,请求https://www.robinhood.com完全正常。我怀疑是重定向导致的,但没找到相关线索。代码里用了自定义HTTPS Agent并加载了本地证书,不确定是不是证书的问题。

最小复现代码

// 最小复现示例
var siteURL = "https://robinhood.com/l/privacy";
import path from 'path';
import sslrootcas from 'ssl-root-cas';
const rootCas = sslrootcas.create();
import {fileURLToPath} from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
rootCas.addFile(path.resolve(__dirname,'intermediate.pem'));
import http from 'node:http';
import https from 'node:https';
import UserAgent from 'user-agents';  
const myhttpsAgent = new https.Agent({ca: rootCas});

const requestcheck = fetch(siteURL, {
   method: "GET",
   headers: {"User-Agent": new UserAgent() },
   agent: myhttpsAgent
})

错误信息

node:internal/errors:477
    ErrorCaptureStackTrace(err);
    ^

TypeError: Protocol "http:" not supported. Expected "https:"
    at new NodeError (node:internal/errors:387:5)
    at new ClientRequest (node:_http_client:177:11)
    at request (node:http:96:10)
    at file:///home/app/node_modules/node-fetch/src/index.js:94:20
    at new Promise (<anonymous>)
    at fetch (file:///home/app/node_modules/node-fetch/src/index.js:49:9)
    at ClientRequest.<anonymous> (file:///home/app/node_modules/node-fetch/src/index.js:236:15)
    at ClientRequest.emit (node:events:525:35)
    at HTTPParser.parserOnIncomingClient [as onIncoming] (node:_http_client:674:27)
    at HTTPParser.parserOnHeadersComplete (node:_http_common:128:17)
    at TLSSocket.socketOnData (node:_http_client:521:22)
    at TLSSocket.emit (node:events:525:35)
    at addChunk (node:internal/streams/readable:315:12)
    at readableAddChunk (node:internal/streams/readable:289:9)
    at TLSSocket.Readable.push (node:internal/streams/readable:228:10)
    at TLSWrap.onStreamRead (node:internal/stream_base_commons:190:23) {
  code: 'ERR_INVALID_PROTOCOL'
}

问题原因与解决方案

原因

这个错误确实是重定向导致的:请求https://robinhood.com/l/privacy时,服务器会返回301/302重定向到一个HTTP协议的URL,但你配置的myhttpsAgent是HTTPS专用Agent,无法处理HTTP请求,因此触发协议不支持的错误。

解决方法

1. 动态适配协议选择Agent

自定义一个agent函数,根据请求的URL协议自动返回HTTP或HTTPS Agent,让node-fetch跟随重定向时能适配不同协议:

const myAgent = (_parsedURL) => {
  // 根据目标URL的协议选择对应的Agent
  if (_parsedURL.protocol === 'http:') {
    return new http.Agent();
  } else {
    return myhttpsAgent; // 你之前配置的HTTPS Agent
  }
};

// 修改fetch调用,使用动态Agent
const requestcheck = fetch(siteURL, {
  method: "GET",
  headers: {"User-Agent": new UserAgent() },
  agent: myAgent
})

2. 禁用自动重定向,手动处理

如果不需要自动跟随重定向,可以设置redirect: 'manual',手动处理响应中的重定向地址:

const requestcheck = fetch(siteURL, {
  method: "GET",
  headers: {"User-Agent": new UserAgent() },
  agent: myhttpsAgent,
  redirect: 'manual'
}).then(res => {
  if (res.status >= 300 && res.status < 400) {
    const redirectUrl = res.headers.get('Location');
    console.log('重定向地址:', redirectUrl);
    // 这里可以根据redirectUrl的协议,选择对应的Agent发起新请求
  }
});

3. 先排查重定向情况

可以先临时去掉Agent,请求URL查看重定向详情,确认是否存在HTTP协议的重定向地址:

fetch(siteURL, { redirect: 'manual' })
  .then(res => console.log('状态码:', res.status, '重定向地址:', res.headers.get('Location')));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 15:30:22