今天碰到了一个跨域问题, 折腾了半天, 终于解决了.
项目背景: 采用前端模版框架 ant design 的脚手架 antd-admin 做开发时, 在本地做开发时, 发现即使设置成 post 方法, 也会通过 get 发送请求. 逐步查询发现采用的都是 JSONP 格式请求. 而 JSONP 的缺点则是: 它只支持 GET 请求而不支持 POST 等其它类型的 HTTP 请求; 它只支持跨域 HTTP 请求这种情况, 不能解决不同域的两个页面之间如何进行 JavaScript 调用的问题.
于是查看 util 下面的 request.js 文件, 发现代码如下:
- export default function request (options) {
- if (options.url && options.url.indexOf('//')> -1) {
- const origin = `${options.url.split('//')[0]}//${options.url.split('//')[1].split('/')[0]}`
- if (window.location.origin !== origin) {
- if (CORS && CORS.indexOf(origin)> -1) {
- options.fetchType = 'CORS'
- } else if (YQL && YQL.indexOf(origin)> -1) {
- options.fetchType = 'YQL'
- } else {
- options.fetchType = 'JSONP'
- }
- }
- }
经测试发现本地都走的 JSONP 的类型, 在看下面的代码.
- if (fetchType === 'JSONP') {
- return new Promise((resolve, reject) => {
- jsonp(url, {
- param: `${qs.stringify(data)}&callback`,
- name: `jsonp_${new Date().getTime()}`,
- timeout: 4000,
- }, (error, result) => {
- if (error) {
- reject(error)
- }
- resolve({ statusText: 'OK', status: 200, data: result })
- })
- })
- }
将所有的参数, 作为 url 的参数的后面追加. 于是问了一下前端的大神, 结合现实情况, 总结修改方案如下:
前端框架采用 json 格式请求, 对于 post 的请求先发送 method=OPTIONS 的请求, 如果返回的是 204 状态, 则放过, 然后在发送实际请求.
后端 api 接口曾需要放过 method=OPTIONS 的请求, 并且返回 204 的状态.
具体解决方案:
(1) 注销上面 jsonp 直接返回的代码, 所有请求都采用 json 格式. 放过 204 的状态.
- return fetch(options).then((response) => {
- if (response.status === 204) {
- return response.text()
- }
- ... ...
(2) server 端放过 method=OPTIONS 的请求, 返回 204.
- if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
- header('Access-Control-Allow-Origin: *');
- header('Content-Type:application/json; charset=utf-8');
- header('Access-Control-Allow-Methods:"GET, POST, OPTIONS, PUT, DELETE"');
- header('Access-Control-Allow-Headers: content-type');
- header('Access-Control-Max-Age: 1000');
- http_response_code('204');
- exit;
- }
(3) 对于 json 格式的请求, 也要返回相应的头部.
- case 'JSON':
- // 返回 JSON 数据格式到客户端 包含状态信息
- header('Access-Control-Allow-Origin: *');
- header('Content-Type:application/json; charset=utf-8');
- header('Access-Control-Allow-Methods:"GET, POST, OPTIONS, PUT, DELETE"');
- header('Access-Control-Max-Age: 1000');
- exit(json_encode($data));
因为内部系统初期开发, 暂时没有细节优化. 仅实现功能, 解决问题为主.
来源: http://www.bubuko.com/infodetail-2632254.html