最近自己构建了一个轻量级的 MVC 框架,现在将该MVC用于生产环境的项目中,目前因为项目中有跨域的请求,所以需要做一些CORS授权,但在实际使用出现了一些问题,目前已解决,故做下记录。
服务器:centos
web server: nginx
程序语言:php
框架:MVC
在 js (jQuery、AngluarJS的$http)跨域请求中,有特定头需要传送时,都会预先发起一个OPTIONS 请求,而 MVC 所有请求入口都是从默认文档 index.php 开始,即 http://www.allmai.net/ 或 http://www.allmai.net/?ctrl=home,当我们使用这种路径做跨域请求时,会返回:405 错误。
经过分析,发现OPTIONS请求并没有被 PHP 所捕获,也就是说nginx并没有将OPTIONS请求转发给 php-fpm 而直接返回了405错误,然后各种百度,各种谷歌也没有找到好的解决办法,都是说的直接在 nginx 配置中做捕获,经过改造,大至如下:
set $allmai 0;
if ($request_method = OPTIONS) {
set $allmai "${allmai}1";
}
if ($http_origin = http://www.allmai.net) {
set $allmai "${allmai}1";
}
if ($allmai = 011) {
add_header Access-Control-Allow-Origin ${http_origin};
add_header Access-Control-Allow-Methods GET, POST, OPTIONS;
add_header Access-Control-Allow-Headers token,content-type;
return 204;
}
这个方法是可以解决问题的,但是并不灵活,如果很少的几个跨域客户端(跨域的web js请求,索性叫客户端)可以通过改nginx.conf 来实现,但有十个,二十个甚至更多的时候该方法就不太灵了。最终还是需要将OPTONS请求转发给PHP脚本来处理才方便是。
再经历几个小时的模索,发现如果 OPTIONS 请求有指定了 php 文件路径,那么OPTIONS就会被PHP捕获并处理,这下让我突然有了灵感,原来OPTIONS请求未指定 php 文件路径,导致nginx 不知道如何处理该请求,我们只需将默认请求转发给指定的 php 文件即可,同样我们要修改nginx.conf 文件,如下:
location / {
root /home/www/web;
index index.html index.htm index.php;
rewrite ^(.*)/$ $1/index.php last;
}
经过上面的重定,所有的请求都会用index.php进入,至此就解决了OPTIONS 的 405 错误。