PATCH 方法和 CORS 预检请求存在问题

rem*_*yml 1 php cors symfony ionic-framework

我在开发应用程序 I\xe2\x80\x99m 时遇到问题。\nAPI 使用 PHP Symfony 4,该应用程序是使用 Ionic 4 制作的。

\n\n

我在执行 PATCH 请求时遇到问题。该请求在 POSTMAN 和我的手机上运行得很好\n但我在浏览器(Google Chrome、Firefox)上尝试时遇到了 CORS 问题。

\n\n

我已经询问过,并且了解到 PATCH 请求首先会经过飞行前请求,因此会使用 OPTIONS 方法向我的 API 发送请求。

\n\n

我管理了这个方法并返回了代码 200,然后我允许在我的 index.php 文件中使用正确的标头,如下所示:

\n\n
header(\'Access-Control-Allow-Origin: *\');\nheader("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");\nheader("Access-Control-Allow-Methods: GET, HEAD, PATCH, OPTIONS, POST, PUT");\n
Run Code Online (Sandbox Code Playgroud)\n\n

一开始,我遇到了第一个错误,表明请求没有返回代码 200,因此我在 API 中管理 OPTIONS 方法。\n然后出现以下错误:

\n\n
No \'Access-Control-Allow-Origin\' header is present on the requested resource.\n
Run Code Online (Sandbox Code Playgroud)\n\n

这很奇怪,因为之前没有出现过该错误,并且所有其他请求都有效。

\n\n

此外,我尝试使用 POSTMAN 和 OPTIONS 方法返回正确的标头。

\n\n

你能帮助我吗?

\n\n

抱歉英语很粗糙。

\n

Mic*_*Mic 8

对于将来发现此问题的任何人,我已经重现了这些确切的症状,并解决了我的问题。简而言之,当在客户端指定该方法时(例如在选项中fetch),PATCH具体是区分大小写的,而其他方法则不区分大小写。需要大写。

据我所能推断出的最佳解释是,尽管RFC7230规定方法应该大写,但它们也区分大小写。浏览器通过自动大写其中几个来平滑这个问题,我相信基于RFC7231,它定义了许多常用方法,但没有定义 PATCH。考虑以下从客户端发起的请求。

fetch('https://stackoverflow.com', 
  { method: 'post', 
    body: JSON.stringify({message: 'testing a cors issue'}), 
    headers:  {'Content-Type': 'application/json'}
  }
)
Run Code Online (Sandbox Code Playgroud)

至少 Chromium 浏览器的正常行为是自动将Access-Control-Request-MethodCORS 预检标头中的方法大写,而不管我的 JavaScript 在 fetch 调用中使用的大写形式如何。

使用大写 post 方法的预检请求

同样,如果方法是DELETE,浏览器也会在预检时自动将其大写。

但是,我发现该PATCH方法(稍后在RFC5789中定义)被视为自定义 HTTP 方法,因为它没有强制大写。因此,它区分大小写,这在 CORS 预检期间可以观察到。如果客户端应用程序以小写形式指定它patch,则它在 Access-Control-Request-Method 标头中的显示方式是这样的,如果它是大写的,则PATCH它在标头中显示为大写。

预检显示小写补丁方法

当您在 Postman 中选择PATCH方法时,它始终是大写的,这掩盖了问题的根本原因。尽管错误消息与标头有关Access-Control-Allow-Origin,但我看到的根本原因是该方法的区分大小写。

  • 是的,根据 HTTP 规范——以及所有其他 RFC——*所有* HTTP 方法都是区分大小写的。另请参阅 /sf/answers/1919914951/。因此,根据 HTTP 和其他 RFC,“patch”和 PATCH 是不同的方法,而“get”与 GET 等也是不同的方法。因此,为了严格遵守 HTTP/RFC 要求,HTTP 服务器和 HTTP 客户端都不能将“patch”方法视为真正意味着 PATCH,或者将“get”等方法视为意味着 GET 等. 这就是大多数 HTTP 服务器实际上所做的事情。但 HTTP 客户端在实践中所做的事情却是另一回事。 (2认同)
  • 浏览器实际上违反了 HTTP 规范对方法不区分大小写的要求。请参阅 https://github.com/whatwg/fetch/issues/50#issuecomment-188241506。但他们以标准方式违反了它,在 https://fetch.spec.whatwg.org/#concept-method-normalize 中定义,其中表示,*“如果方法是字节大小写不敏感的匹配,则对方法进行规范化对于 DELETE、GET、HEAD、OPTIONS、POST 或 PUT,请将其字节大写。”* 因此,由于 PATCH 不在该列表中,因此浏览器*从不*大写“patch”,也不会使用除该列表中的方法之外的任何其他方法。浏览器对列出的浏览器执行此操作的唯一原因是向后兼容性。 (2认同)