YII2 CORS 踩过的坑

由于项目需求,功能越来越多,小程序容量只有2M,所以改造小程序,在小程序中加入webview,把之前的部分功能提出到webview中。

之前做小程序时有考虑到这个问题,请求API接口有封装JS,于是直接复制过来,想直接复用,webview也采用调用API接口的方式获取数据,毕竟API接口都写好了。OK,直接开干,复制JS,修改为jquery 封装 ajax,

var Request = function (qureyObj)
{
    var headers = getAjaxHeaders();

    $.ajax({
        url: Conf.apiDomain + qureyObj.apiUrl,
        data: qureyObj.parameters || {},
        type: qureyObj.method,
        dataType: 'json',
        beforeSend: function (xhr)
        {
            xhr.withCredentials = true;
            xhr.setRequestHeader('Authorization', headers.Authorization);
            xhr.setRequestHeader('Location', headers.Location);
            xhr.setRequestHeader('city', headers.city);
            xhr.setRequestHeader('addr', headers.addr);
        },
        success: function (res)
        {

            var return_msg = res;
            if (return_msg.code == -1 && return_msg.status == 200)
            {
                //错误回调
                if (qureyObj.failCallback) qureyObj.failCallback();
                return;
            }

            if (qureyObj.successCallback) qureyObj.successCallback(res);
        },
        error: function (data)
        {
            if (qureyObj.failCallback) qureyObj.failCallback();
        },
        complete: function ()
        {
            if (qureyObj.completeCallback) qureyObj.completeCallback();
        }
    });
}

后端YII2框架,之前有做登录权限认证,放在header中,所以要修改后端API接口代码,添加CORS过滤器,增加允许跨域域名,header,

public function behaviors()
    {
        $behaviors = parent::behaviors();

        // add CORS filter
        $behaviors['corsFilter'] = [
            'class' => Cors::className(),
            'cors' => [
                'Origin' => ['https://wview.xxx.com', 'http://w.xxx.com'],
                'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
//                'Access-Control-Allow-Credentials' => true,
                'Access-Control-Request-Headers' => ['Authorization', 'Location', 'city', 'addr']
            ]
        ];

        $behaviors = ArrayHelper::merge($behaviors, [
            'rateLimiter'=>[
                'enableRateLimitHeaders'=>false
            ],
            'authValidate'      => [
                'class'     => HttpBasicAuth::class,
                //access-token 部分接口需要验证,需要排除
                'optional'  => ['register','login','sp-login','wechat-pay','wechatpay-notify','pull-msg'],
            ]
        ]);

        return $behaviors;
    }

仿佛一切都在掌握之中,直接调用之前的接口,404,擦,不可能啊,什么情况!
!!!坑来了!!!!!!URL直接访问借口没问题,url地址肯定是对的,注释掉权限认证,接口也没问题,有数据!!!难道是CORS设置不对,看看源码Cors类 就那几个选项,每个都设置了N种情况,还是404。。。。实在是没办法了,一行一行找问题,一个点一个点排除,最后发现只要在 jquery.ajax beforeSend 设置header头,就404, 注释掉,就OK,这就神奇了!!!!这个问题足足浪费了我5个小时时间。。。。

也看了阮一峰大神的关于跨域cors 的一篇文章,标题忘记了,写得很详细。也知道了简单请求,非简单请求。仍然没有排查出问题。最后想着从源码调试,用Yii::error 一步一步记录信息,终于发现URLManager 404 ,,,干。。。是真的没找到URL地址。

添加了自定义header,请求就变为非简单请求,ajax会有两次请求,第一次为预请求,重点,预请求的method:OPTIONS 

由于API接口继承的 Restful 风格的congroller ,所以URLmanager 也是Restful 风格的规则,里面没有 OPTIONS,所以404。。。。。增加一条规则

'OPTIONS <modules>/<controller>/<action>' => '<modules>/<controller>/<action>',

搞定,如此简单的问题,竟然坑了我5个小时。。。基础还是必须得掌握的,mark 一下,希望大家不要踩这个坑

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值