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

React/Next.js中Fetch自定义Header触发net::ERR_HTTP2_PROTOCOL_ERROR求助

排查方向与解决方案建议

Hey Corrie, 我帮你梳理几个关键的排查方向,这个问题大概率和CORS预检请求的处理、HTTP2配置或者服务器端的头权限有关:

1. 确认服务器是否正确响应OPTIONS预检请求

当你添加merchant-id这种自定义请求头时,浏览器会自动发起OPTIONS预检请求,用来确认服务器是否允许该自定义头。如果服务器没有正确处理这个请求,就会导致后续的GET请求失败:

  • 打开浏览器开发者工具的「Network」面板,勾选「Disable cache」,重新发起请求,查看是否有OPTIONS请求发出:
    • 如果没有OPTIONS请求:可能是浏览器缓存了旧的预检结果,或者服务器直接拦截了OPTIONS方法;
    • 如果有OPTIONS请求:检查响应头是否包含以下关键字段:
      • Access-Control-Allow-Origin:必须匹配你的网站域名(或者设为*,但生产环境不建议);
      • Access-Control-Allow-Headers:必须明确包含merchant-id(不能只写*,因为带自定义头的请求需要指定具体允许的头);
      • Access-Control-Allow-Methods:必须包含GET方法。

2. 排查HTTP2协议相关的服务器配置

你的报错是net::ERR_HTTP2_PROTOCOL_ERROR,说明问题可能和HTTP2的特性有关:

  • 部分服务器在处理OPTIONS请求时,HTTP2配置存在兼容性问题,比如对请求头的长度、格式限制更严格;
  • 可以尝试强制使用HTTP/1.1发起请求(部分浏览器或Fetch API支持通过配置指定),或者用Postman等工具模拟HTTP2环境下的请求,对比浏览器的差异;
  • 检查merchant-id的头名和值是否符合HTTP2规范(比如头名是否有大小写错误、值是否包含特殊字符),虽然你在HTTP客户端测试正常,但浏览器的HTTP2实现可能有不同的校验逻辑。

3. 验证自定义头的传递与服务器校验逻辑

虽然你在HTTP客户端测试正常,但浏览器环境下有Origin限制,可能存在差异:

  • 确认服务器是否对请求的Origin字段有严格校验:浏览器会自动带上当前网站的Origin,而HTTP客户端可能没有这个头,服务器可能只允许特定Origin的请求;
  • 尝试简化merchant-id的值(比如用test123这种无特殊字符的内容),排除值的格式问题导致的服务器拒绝。

4. 检查Next.js的代理或API路由配置(如果使用)

如果你是直接在前端发起请求到第三方支付网关,那是浏览器CORS问题;但如果用了Next.js的API路由做代理,需要确保代理配置正确传递自定义头:

  • 比如在pages/api/payfast.js中,要将请求头里的merchant-id完整转发到目标服务器:
    export default async function handler(req, res) {
      const { merchantId } = req.headers;
      const response = await fetch(`https://api.payfast.co.za/ping?testing=true`, {
        method: 'GET',
        headers: {
          'Content-Type': 'text/plain',
          'merchant-id': merchantId,
        },
      });
      const data = await response.json();
      res.status(response.status).json(data);
    }
    
  • 同时要确保代理路由的CORS配置正确,允许前端网站的Origin访问。

5. 补充错误捕获代码,获取更详细的错误信息

你可以给Fetch请求加上完整的错误捕获,以便看到更具体的错误细节:

const request = new Request( 
  `https://api.payfast.co.za/ping?testing=true`, 
  { 
    method: "GET", 
    headers: { 
      "Content-Type": "text/plain", 
      "merchant-id": "xxxx", 
    }, 
  } 
); 

fetch(request)
  .then((res) => {
    if (!res.ok) throw new Error(`HTTP状态码异常: ${res.status} ${res.statusText}`);
    return res.json();
  })
  .then((data) => console.log('请求成功:', data))
  .catch((err) => console.error('请求失败详情:', err));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 07:37:57