CORS 预检请求返回 HTTP 405

Posted

技术标签:

【中文标题】CORS 预检请求返回 HTTP 405【英文标题】:CORS preflight request returning HTTP 405 【发布时间】:2013-10-24 21:40:43 【问题描述】:

我正在尝试创建一个 RESTful Web 服务,但在实现 PUT 请求时遇到了困难。我已尝试关注此网站上的其他答案以及 Mozilla 的各种文章,但未能成功。

请求是从域wwwtest.dev-box 生成的,它将发送到test.dev-box(基本上是一个前端应用程序调用后端应用程序)。以下是我从 Live HTTP 标头中捕获的标头:

http://test.dev-box/resource/v1/data/user/1

OPTIONS /resource/v1/data/user/1 HTTP/1.1
Host: test.dev-box
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Firefox/24.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Origin: http://wwwtest.dev-box
Access-Control-Request-Method: PUT
Connection: keep-alive

HTTP/1.1 405 Method Not Allowed
Date: Wed, 16 Oct 2013 16:15:58 GMT
Server: Apache/2.2.15 (Red Hat)
x-powered-by: php/5.3.27
Access-Control-Allow-Origin: http://wwwtest.dev-box
Access-Control-Allow-Methods: POST, GET, PUT, OPTIONS
Access-Control-Max-Age: 1728000
Content-Length: 0
Allow: PUT
Cache-Control: no-cache
Connection: close
Content-Type: text/html; charset=UTF-8

我正在使用一个框架,所以所有内容都被路由到 web.php,它在页面顶部包含以下代码(取自this MDN article):

if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') 
    header('Access-Control-Allow-Origin: http://wwwtest.dev-box');
    header('Access-Control-Allow-Methods: POST, GET, PUT, OPTIONS');
    header('Access-Control-Max-Age: 1728000');
    header("Content-Length: 0");
    header("Content-Type: text/plain");
 else 
    header("HTTP/1.1 403 Access Forbidden");
    header("Content-Type: text/plain");

在我的代码发出 PUT 请求之前,它首先发送 CORS 预检 OPTIONS 请求(从上面的捕获中可以看到)。必要的标头应附加到响应中,并告诉请求者允许 PUT。不幸的是,正如您从上面的响应标头中看到的那样,即使 PUT 在响应 access-control-allow-methods 中,它仍然返回 405 Method Not Allowed。

这是我正在使用的框架 (Silex) 的 .htaccess 文件:

<IfModule mod_rewrite.c>
    Options -MultiViews

    RewriteEngine On
    RewriteCond %REQUEST_FILENAME !-f
    RewriteRule ^ web.php [QSA,L]
</IfModule>

【问题讨论】:

【参考方案1】:

我发现答案是 Apache 和框架配置之间的交叉。

    对于 Apache 配置,您可以将以下内容放入您的 VirtualHost 指令中,或者放入所请求域的 .htaccess 文件中(如果它在 .htaccess 中,请记住使用 IfModule mod_headers.c 标记进行封装)。在 mod_rewrite 重定向到的页面上设置标题不起作用:

    标头集 Access-Control-Allow-Origin "http://wwwtest.dev-box"

    标头集 Access-Control-Allow-Methods "GET,POST,HEAD,DELETE,PUT,OPTIONS"

    对于 Silex 配置,将以下内容放入您的应用程序路由中。它基本上为它收到的任何 OPTIONS 请求发送 HTTP 200 OK。在Silex Google Group上找到的代码:

    $app->match("url", function($url) 使用 ($app) 返回“确定”; )->assert('url', '.*')->method("OPTIONS");

需要完成这两个步骤才能使 RESTful 应用程序正常运行。

【讨论】:

【参考方案2】:

405 是指实际的预检/OPTIONS 请求。您的服务器完全拒绝预检,因为您的服务器通常不接受 OPTIONS 请求。您需要修改服务器配置以接受 OPTIONS 请求。仅在 PHP 文件中包含代码可能还不够。您的 Web/应用程序服务器很可能不知道这个动词,并且在请求到达您的 PHP 代码之前拒绝了该请求。

【讨论】:

在我读过的任何文章中,我都没有听说过 Apache 会直接阻止 OPTIONS 请求。你有这方面的任何信息,或者我可以如何配置它的想法? 嗯,仔细看,您的 PHP 代码似乎正在执行,因为响应中包含 CORS 标头。您的 PHP 代码中的某些内容很可能会返回 405。您必须发布所有 PHP 代码。 不可能发布代码,但我正在使用 Silex,它是一个基于 Symfony2 的框架,如果有帮助的话。我没有对访问限制或修改标头等做任何事情。只是试图 PUT 到路由并取回一些数据。 这个框架和大多数其他框架一样,使用 mod_rewrite 将流量重定向到处理程序。这会导致任何问题吗?我已经在问题中发布了 .htaccess 文件内容。 感谢您的帮助 Ray,您的回答帮助我更深入地了解 Apache,这让我找到了问题所在。干杯!

以上是关于CORS 预检请求返回 HTTP 405的主要内容,如果未能解决你的问题,请参考以下文章

对 CORS 预检的响应具有 HTTP 状态代码 405

CORS 问题? - 预检响应包含无效的 HTTP 状态代码 405

CORS 预检请求返回带有 Windows 身份验证的 HTTP 401

HTTP的options方法作用

从 javascript Web 服务客户端发送 CORS POST 请求返回 http 405 错误

CORS - ...不支持 http 方法 'OPTIONS'