options 请求的出现和作用我就不多叙述了,可以上网查到很多相关的资料, 我主要想谈一下options 到底请求的是你post请求的地址吗?
答案是错误,Options请求并不是跟你POST请求的同一个地址, 下面请看原因及我个人的测试。
最近在使用thinkcmf做接口开发, thinkcmf 内置有接口基类 apiportalcontrollerRestBaseController
文件位置在 vendor/thinkcmf/cmf/src/controller/RestBaseController.php
在此文件中,有在header中的参数 : XX-Token,XX-Api-Version,XX-Wxapp-AppId
在success 和 error 方法中设置了允许跨域, 并在header中带有的参数
success方法:
protected function success($msg = '', $data = '', array $header = [])
{
$code = 1;
$result = [
'code' => $code,
'msg' => $msg,
'data' => $data,
];
$type = $this->getResponseType();
$header['Access-Control-Allow-Origin'] = '*';
$header['Access-Control-Allow-Headers'] = 'X-Requested-With,Content-Type,XX-Device-Type,XX-Token,XX-Api-Version,XX-Wxapp-AppId';
$header['Access-Control-Allow-Methods'] = 'GET,POST,PATCH,PUT,DELETE,OPTIONS';
$response = Response::create($result, $type)->header($header);
throw new HttpResponseException($response);
}
error 方法:
protected function error($msg = '', $data = '', array $header = [])
{
$code = 0;
if (is_array($msg)) {
$code = $msg['code'];
$msg = $msg['msg'];
}
$result = [
'code' => $code,
'msg' => $msg,
'data' => $data,
];
$type = $this->getResponseType();
$header['Access-Control-Allow-Origin'] = '*';
$header['Access-Control-Allow-Headers'] = 'X-Requested-With,Content-Type,XX-Device-Type,XX-Token,XX-Api-Version,XX-Wxapp-AppId';
$header['Access-Control-Allow-Methods'] = 'GET,POST,PATCH,PUT,DELETE,OPTIONS';
$response = Response::create($result, $type)->header($header);
throw new HttpResponseException($response);
}
我自己重写了基类,不使用自带的基类。
在基类中,我也将header中携带的认证参数做了更改, success方法如下。
protected function success($msg = '', $data = [], array $header = [])
{
$code = 1;
$result = [
'code' => $code,
'msg' => $msg,
'data' => $data,
];
$type = $this->getResponseType();
$header['Access-Control-Allow-Origin'] = '*';
$header['Access-Control-Allow-Headers'] = 'X-Requested-With,Content-Type,read-Device-Type,read-Token';
$header['Access-Control-Allow-Methods'] = 'GET,POST,PATCH,PUT,DELETE,OPTIONS';
$response = Response::create($result, $type)->header($header);
throw new HttpResponseException($response);
}
此时,问题就来了,在使用post 访问接口的时候一直提示跨域,
页面代码
<html>
<head></head>
<body>
<script src="https://www.showdoc.cc/static/jquery.min.js"></script>
<script>
$(function(){
$.ajax(
{
url:'http://wxofficial.kevink.club/api/frontend/public/auth',
type:'post',
dateType:'json',
headers:{'Content-Type':'application/json;charset=utf8','read-Device-Type':'wxweb', 'read-Token': '95a426f84c28a4b0d91defc8ddd025c2'},
success:function(data){
//console.log("sucess");
console.log(data)
},
error:function(data){console.log("error");}
}
);
})
</script>
</body>
</html>
返回结果:
注意红框标志, 请求的Access-Control-Allow-Headers 并不是我设置在自己基类中的值。 我设置的是: X-Requested-With,Content-Type,read-Device-Type,read-Token
由此可见,options 请求肯定与post请求,访问的接口不同,如果相同,那么不会出现跨区情况。下面我就来找一下options 请求到底去访问了哪。
如果我访问thinkcmf 框架的api, 会出现以下提示
那就来找找这个地址访问到了哪,最终定位到:vendor/thinkcmf/cmf-api/src/home/controller/IndexController.php
<?php
// +----------------------------------------------------------------------
// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013-2017 http://www.thinkcmf.com All rights reserved.
// +----------------------------------------------------------------------
// | Author: Dean <zxxjjforever@163.com>
// +----------------------------------------------------------------------
namespace api\home\controller;
use cmf\controller\RestBaseController;
class IndexController extends RestBaseController
{
// api 首页
public function index()
{
$this->success("恭喜您,API访问成功!", [
'version' => '1.1.0',
'doc' => 'http://www.thinkcmf.com/cmf5api.html'
]);
}
}
那我们就重写一下home模块, 在api 文件夹下创建home模块, 写一个IndexController 控制器接口,继承我自己的基类文件 RestBaseController.
再去访问下刚才提示跨域的接口, 发现在header 中还是有 XX-Token, XX-DeviceType.
说明还是没有解决到问题。
最终结论
options请求访问的接口地址跟post访问的接口地址不是同一个地址,如果是同一个地址,header中不应该出现 XX-Token 而是 read-Token.