最近自己構建了一個輕量級的 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 錯誤。