webman按照手册来,在中间件中配置了跨域,但是请求的时候还是出现了404问题
以下是中间件代码:
<?php
namespace support\middleware;
use Webman\MiddlewareInterface;
use Webman\Http\Response;
use Webman\Http\Request;
/**
* 跨域测试
* 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;
}
}
config目录下的配置
<?php
return [
'' => [
support\middleware\AccessControl::class
]
];
前端请求代码(使用了Jquery):
$.ajax({
url : 请求地址,
type : "post",
dataType : 'JSON',
data : data.field,
success : function(response){
},
error : function (err) {
}
});
但是浏览器的ajax请求出错
跨域的问题没办法解决,是不是哪一步操作错误了呢?
7个回答
年代过于久远,无法发表回答
路由配置贴下。
<?php
namespace app\route;
use Webman\Route;
Route::post('/login' , 'app\admin\controller\Auth\Admin@login');
路由代码,其他的没有动过
这个是我路由代码
用postman请求是没有问题的,意味着路由配置应该是没有问题
用 Route::any(),截图里浏览器发起的是OPTIONS请求,不是post
@1:any方法中并不包括OPTIONS,我手动在Route.php文件加上去之后,请求会直接转发到控制器逻辑,这样不符合CORS逻辑,OPTIONS是浏览器发起一种“试探”吧,不应该直接转发到控制器。由于回复发不了图,我在下面再发图吧。
修改前的any方法
修改后的any方法
请求修改前的any,结果如提问一样是404
请求修改后的any,结果如下图,请求直接就访问到了业务逻辑,由于OPTIONS是不带任何的业务参数的,所有很大可能会报错。
升级下
webman-framework
,webman-framework
从1.0.1开始路由增加了options支持。所以你的路由应该设置为:
这样将options路由和post路由分开,options路由就不用处理业务逻辑了。
是不是项目中每个跨域api接口(几乎全部都是)都得做同样OPTIONS的路由?
你可以直接在中间件里判断下当前是否是options请求,如果是则直接返回跨域header,不继续执行正常逻辑。这样就不用每个接口都设置options路由。中间件代码类似如下:
再说说options请求
浏览器在特定情况下才会发起opitons请求。
一般情况下ajax请求不会触发options请求。我这里经过测试,在ajax里参数设置
contentType:'application/json'
时,会触发options请求。如果你的项目发起了options请求,可以看下是符合哪个条件触发的,是否可以避免。
感谢,升级和配置中间件之后,是可以了。我看fast-route是支持group的,但是webman没把group这个方法封装进去,慢慢来吧。祝webman发展越来越好!!
反复测试过之后,由于文档中没说明框架的生命周期。我测过之后,发现请求后,先是路由再到中间件的。也就是说,其实在中间件中判断请求方式是否为OPTIONS不重要了。因为当ajax触发OPTIONS请求时,如果在路由文件没有写OPTIONS的对应路由时,就直接会报404,不会到中间件里面去了。代码如下:
这样又回到了所有的路由都写一遍OPTIONS的路由的情况了,这样很累赘
问题如何重现?
请求时,代码如下:
以下为个人的解决方法:
找到以下文件:vendor/workerman/webman-framework/src/App.php
在onMessage方法中添加一下代码:
然后重新开启workerman,完成!!!
用 Route::any(),然后中间件里判断OPTIONS就好了
@1:使用any()也是可以,这个得看看业务逻辑需要吧
楼主的方法有效,但需要和 walkor 大佬的 app/middleware/AccessControlTest.php 中间件一起配合使用; view 前后端分离环境 ( jquery ajax , postman 无上述跨域问题)