由于项目需求,功能越来越多,小程序容量只有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 //' => '//',
搞定,如此简单的问题,竟然坑了我5个小时。。。汗颜,看来基础还是必须得掌握的,mark 一下,希望大家不要踩这个坑