CORS预检请求返回HTTP 405

Mat*_*t K 7 php http-headers cors silex

我正在尝试创建一个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
Run Code Online (Sandbox Code Playgroud)

我正在使用一个框架,所以一切都被路由到web.php,它在页面顶部包含以下代码(取自这篇MDN文章):

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");
}
Run Code Online (Sandbox Code Playgroud)

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

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

<IfModule mod_rewrite.c>
    Options -MultiViews

    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ web.php [QSA,L]
</IfModule>
Run Code Online (Sandbox Code Playgroud)

Mat*_*t K 12

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

  1. 对于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"

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

    $ app-> match("{url}",function($ url)use($ app){return"OK";}) - > assert('url','.*') - > method("OPTIONS") );

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