<?php
namespace support\middleware;
use Webman\MiddlewareInterface;
use Webman\Http\Response;
use Webman\Http\Request;
/**
* 跨域測(cè)試
* Class AccessControl
* @package support\middleware
*/
class AccessControl implements MiddlewareInterface
{
public function process(Request $request, callable $next) : Response
{
/** @var Response $response */
$response = $next($request);
$response->withHeaders([
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => 'GET,POST,PUT,DELETE,OPTIONS',
'Access-Control-Allow-Headers' => 'Content-Type,Authorization,X-Requested-With,Accept,Origin',
]);
return $response;
}
}
<?php
return [
'' => [
support\middleware\AccessControl::class
]
];
$.ajax({
url : 請(qǐng)求地址,
type : "post",
dataType : 'JSON',
data : data.field,
success : function(response){
},
error : function (err) {
}
});
<?php
namespace app\route;
use Webman\Route;
Route::post('/login' , 'app\admin\controller\Auth\Admin@login');
這個(gè)是我路由代碼
@1:any方法中并不包括OPTIONS,我手動(dòng)在Route.php文件加上去之后,請(qǐng)求會(huì)直接轉(zhuǎn)發(fā)到控制器邏輯,這樣不符合CORS邏輯,OPTIONS是瀏覽器發(fā)起一種“試探”吧,不應(yīng)該直接轉(zhuǎn)發(fā)到控制器。由于回復(fù)發(fā)不了圖,我在下面再發(fā)圖吧。
public static function any($path, $callback)
{
static::addRoute(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD' ], $path, $callback);
}
public static function any($path, $callback)
{
static::addRoute(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD' , 'OPTIONS'], $path, $callback);
}
是不是項(xiàng)目中每個(gè)跨域api接口(幾乎全部都是)都得做同樣OPTIONS的路由?
你可以直接在中間件里判斷下當(dāng)前是否是options請(qǐng)求,如果是則直接返回跨域header,不繼續(xù)執(zhí)行正常邏輯。這樣就不用每個(gè)接口都設(shè)置options路由。中間件代碼類似如下:
class AccessControl implements MiddlewareInterface
{
public function process(Request $request, callable $next) : Response
{
/** @var Response $response */
if ($request->method() == 'OPTIONS') {
response = response('');
} else {
$response = $next($request);
}
$response->withHeaders([
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => 'GET,POST,PUT,DELETE,OPTIONS',
'Access-Control-Allow-Headers' => 'Content-Type,Authorization,X-Requested-With,Accept,Origin',
]);
return $response;
}
}
再說說options請(qǐng)求
瀏覽器在特定情況下才會(huì)發(fā)起opitons請(qǐng)求。
1. 使用了下面任一HTTP 方法:
PUT/DELETE/CONNECT/OPTIONS/TRACE/PATCH
2. 人為設(shè)置了以下集合之外首部字段:
Accept/Accept-Language/Content-Language/Content-Type/DPR/Downlink/Save-Data/Viewport-Width/Width
3. Content-Type 的值不屬于下列之一:
application/x-www-form-urlencoded、multipart/form-data、text/plain
一般情況下ajax請(qǐng)求不會(huì)觸發(fā)options請(qǐng)求。我這里經(jīng)過測(cè)試,在ajax里參數(shù)設(shè)置contentType:'application/json'
時(shí),會(huì)觸發(fā)options請(qǐng)求。
$.ajax({
url : '地址',
type : "post",
contentType:'application/json', // 這里
success : function(response){},
error : function (err) {}
});
如果你的項(xiàng)目發(fā)起了options請(qǐng)求,可以看下是符合哪個(gè)條件觸發(fā)的,是否可以避免。
感謝,升級(jí)和配置中間件之后,是可以了。我看fast-route是支持group的,但是webman沒把group這個(gè)方法封裝進(jìn)去,慢慢來吧。祝webman發(fā)展越來越好??!
<?php
Route::options('/login' , function(){
return response('');
});
Route::post('/login' , 'app\admin\controller\Auth\Admin@login');
$.ajax({
url : routeUrl.login,
type : "post",
dataType : 'JSON',
data : data.field,
header:{token:'12312321'},
success : function(response){
},
error : function (err) {
console.log(err)
}
});
以下為個(gè)人的解決方法:
找到以下文件:vendor/workerman/webman-framework/src/App.php
在onMessage方法中添加一下代碼:
public function onMessage(TcpConnection $connection, $request)
{
//添加以下代碼
if($request->method() == 'OPTIONS'){
$response = response('');
//規(guī)則自己定
$response->withHeaders([
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => 'GET,POST,PUT,DELETE,OPTIONS',
'Access-Control-Allow-Headers' => 'Content-Type, Authorization, X-Requested-With, Accept, Origin, Authorization, Headers, token',
'Access-Control-Request-Headers' => 'Headers, token',
]);
static::send($connection, $response, $request);
return null;
}
.....以下為官方代碼,省略
}
然后重新開啟workerman,完成?。?!