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

服务器CORS策略允许PATCH,为何我的PATCH请求仍被拦截?

问题描述

根据Gist API的说明,它明确允许所有*主机和PATCH方法:

access-control-allow-origin: *
access-control-allow-methods: GET,PUT,PATCH,OPTIONS,POST

但当我在运行于http://localhost的开发应用中,通过浏览器fetch API向私有Gist发送带有有效令牌的PATCH请求时,Chrome却将其拦截,提示:

从源'http://localhost'获取'https://api.github.com/gists/c4c...86d'的请求已被CORS策略阻止:预检响应中的Access-Control-Allow-Methods不允许使用patch方法。

  • 我已尝试使用非localhost地址,如http://127.0.0.1、http://local.host等。
  • 据我理解,由于允许源设置为*,HTTP与HTTPS跨域也不应成为问题。

有趣的是,预检请求出现在被拦截的PATCH请求之后:

网络请求截图1
网络请求截图2

  1. 明明服务器允许PATCH,为何Chrome仍声称该方法不被允许?
  2. 为何Chrome在我的PATCH请求之后才发送预检请求?

问题1解答

核心原因是私有Gist的预检OPTIONS请求未携带认证令牌,导致GitHub返回的CORS头不包含PATCH方法。

Gist API文档标注的CORS配置是针对公开资源的,当请求私有Gist时,GitHub要求请求必须携带认证信息。但根据CORS规范,浏览器发送预检OPTIONS请求时,默认不会携带Authorization令牌。此时GitHub对未认证的OPTIONS请求返回的Access-Control-Allow-Methods头,仅包含GET、OPTIONS等基础方法,不会包含PATCH,因此Chrome判定该方法不被允许。

另外存在极小概率的大小写问题:如果请求中使用了小写patch方法名,而GitHub返回的头中是大写PATCH,不过现代浏览器一般会忽略方法名的大小写,这个可能性极低。

问题2解答

你看到的“PATCH请求在前,预检在后”是Chrome网络面板的视觉误导,实际流程为:

  1. 浏览器尝试发送PATCH请求,但检测到这是跨域且需要预检的请求(PATCH属于非简单方法,同时请求携带了认证令牌),因此立即取消了该PATCH请求。
  2. 随后浏览器发送正式的OPTIONS预检请求。

在Chrome网络面板中,被取消的PATCH请求会保留在列表中,后续的OPTIONS请求会排在它后面,看起来像是PATCH先发送。你可以检查PATCH请求的状态,应该显示为“已取消(Cancelled)”,以此验证这个流程。如果开启面板的“保留日志(Preserve log)”选项,就能清晰看到完整顺序:OPTIONS先发送,预检通过后才会发送PATCH请求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 04:23:10