Dva: fetch 跨域问题

Created on 17 Nov 2016  ·  18Comments  ·  Source: dvajs/dva

在model层effects中调用service层方法,代码如下:

// 引入service
import { login } from '../services/authentication';
// effects
*login({ payload: { currentUser } }, { select, call, put }) {
      const data = yield call(login, {
        "mobile": currentUser.userName,
        "password": currentUser.password
      });
      console.log('my response data is:', data);

浏览器查看服务端请求正常,但是打印data显示checkstatus产生的错误,checkstatus前返回的response为:

body:(...)
bodyUsed:false
headers:Headers
    __proto__: Headers
ok:false
status:0
statusText:""
type:"opaque"
url:""

请问可能是哪里出的问题呢,浏览器查看请求返回状态200,这里得到的http状态码却为0,是我的effects还是fetch的问题?

277 对了,这个添加headers的问题依然存在,也是dva6.0的版本,会不会是isomorphic-fetch的问题?

faq question

Most helpful comment

  1. fetch 抛出的错误没有清晰定位出问题,换了一种Promise方案(axios ) 才知道是跨域问题
    2.网上找到一篇轻松解决跨域问题的贴子,设置了mode : no- cors ,结果走了一些弯路
    3.最后通过阅读fetch 官方文档因此对fetch有了更深入的了解,最后通过设置mode ; cors 解决了问题。
    总结:跨域问题解决的关键还在于对xhr 和http协议的理解,指定mode为Cors 与no - cors 的最大区别是cors 在发请求前先道过option s 请求根据request header 判断服务端是否支持跨域。

All 18 comments

不是 effect 的问题,应该和 fetch 有关。跨域了?

是做了跨域请求,换成axios 做请求一切正常,是fetch 要配置什么参数才能支持跨域吗?

没具体试过,不过看 fetch 文档,说是跨域处理和 XMLHTTPRequest 是一致的。会不会和 cookie 没带过去有关?https://www.npmjs.com/package/whatwg-fetch#sending-cookies

我的项目里,服务端是GO语言写的,只要在服务端配置支持/允许跨域,客户端的fetch不需要额外配置;

我觉得@xaviertung 可以考虑查看服务端的日志来分析/定位问题,如果是鉴权问题,就解决鉴权的事情:)

在 2016年11月18日,上午8:30,chencheng (云谦) [email protected] 写道:

没具体试过,不过看 fetch 文档,说是跨域处理和 XMLHTTPRequest 是一致的。会不会和 cookie 没带过去有关?https://www.npmjs.com/package/whatwg-fetch#sending-cookies https://www.npmjs.com/package/whatwg-fetch#sending-cookies

You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub https://github.com/dvajs/dva/issues/282#issuecomment-261413729, or mute the thread https://github.com/notifications/unsubscribe-auth/ACv7UniRkGq0Uv8XFBUeNMe5jBeGyWpQks5q_PGPgaJpZM4K0zn8.

谢谢,问题解决了,是mode和credentials设置的问题。

怎么解决的,说下方案? 之后可能会有其他人遇到。

  1. fetch 抛出的错误没有清晰定位出问题,换了一种Promise方案(axios ) 才知道是跨域问题
    2.网上找到一篇轻松解决跨域问题的贴子,设置了mode : no- cors ,结果走了一些弯路
    3.最后通过阅读fetch 官方文档因此对fetch有了更深入的了解,最后通过设置mode ; cors 解决了问题。
    总结:跨域问题解决的关键还在于对xhr 和http协议的理解,指定mode为Cors 与no - cors 的最大区别是cors 在发请求前先道过option s 请求根据request header 判断服务端是否支持跨域。

@sorrycc 老师, 我跨域fetch也遇到了一些问题,使用fetch请求后控制台出现200的Options请求,后台能进断点,判断方式为GET(我真正的请求),前端使用response.json()也能拿到后台数据,但是控制台就是没有GET请求的记录,只有Options的,换用ajax一切正常控制台同时有Option和GET请求

@AsceticBoy 听起来应该是控制台的问题,配了过滤了?

@xaviertung 跨站前端只需要设置mode ; cors?
我在header加了 credentials: 'include',就要报错,说请求不允许。
现在调试好麻烦,我每次都要改成本域然后再编译好前端,放到后端工程里面进行调试。
我用的nginx+tomcat(spring)后台需要怎么设置呢?谢谢

@wuyongdec 需要查看服务端是否开放了允许跨域配置。

@wuyongdec dora支持跨域调试

@xaviertung 服务器端开了的,但是在加了credentials: 'include'的时候服务器就拒绝了。

@jingchenxu 有没有文档?

我遇到这个问题是因为没有在.roadhogrc配置proxy。提示也是报跨域的问题。

target的http://jsonplaceholder.typicode.com/ 改成你自己的服务器地址
"proxy": { "/api": { "target": "http://jsonplaceholder.typicode.com/", "changeOrigin": true, "pathRewrite": { "^/api" : "" } } }

@wuyongdec 我也遇到了和你一样的问题,请问你解决了吗?是如何解决的?

前后端分离跨域配置!!! 非cookies 认证 , JWT认证配置 !!
解决不能跨域请求,
首先不要在config.js 设置proxy , 这种配置只能在本地开发使用 , build后失效。

我的方案:
在.env 配置(没有就在根目录创建)
请求api的时候,读取服务器地址。(修改request.js)

nghin/apache/php 服务器加上
add_header Access-Control-Allow-Origin * always; ### (Since Nginx 1.7.5 )

add_header Access-Control-Allow-Methods GET,POST,OPTIONS,HEAD,PUT;
add_header Access-Control-Allow-Headers "Authorization,Content-Type";

前端 fentch:
credentials: 'omit' // 这个代表不发cookies 跨域请求必须
header:{
Authorization: localStorage.getItem('login-token'),
}

其中 “Authorization” 是 不同服务器不同的配置,要看服务器端认证方式

在此记录下我的做法。
如果 域名不一致,请确保后台支持跨域。
不管是 200 400 500,都必须携带 Access-Control-Allow-Origin 等信息。
fetch header 中 携带下列两个参数

{
  mode: 'cors',
  credentials: 'include',
}

nginx 服务器写入下列header

add_header Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Keep-Alive,User-Agent,Cache-Control,Content-Type,Authorization,sbid
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Origin: 你的域名

此时 get post delete 等都可正常工作,
但是遇到另一个问题 nginx 在返回 401 时,丢失了 Access-Control-Allow-Origin 等信息,导致 401 时无法获取到 response 的 status (https://github.com/github/fetch/issues/201#issuecomment-141777867)
解决方式,nginx 添加 always
Syntax: | add_header name value [always];
http, server, location, if in location

server {
  listen       80;
  server_name  www.google.com;

  #charset koi8-r;
  #access_log  /var/log/nginx/host.access.log  main;

  location / {
    if ($request_method = 'OPTIONS') { 
      add_header Access-Control-Allow-Origin 'http://www.baidu.com' always;
      add_header Access-Control-Allow-Credentials 'true' always; 
      add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS' always;
      add_header Access-Control-Allow-Headers 'Keep-Alive,User-Agent,Cache-Control,Content-Type,Authorization,sbid' always;    
      return 200; 
    }

    root   /home/wwwroot/php;
    index  index.php index.html index.htm;
    try_files $uri $uri/ /index.php?$args;
  }

  location ~ \.php$ {
    add_header Access-Control-Allow-Origin 'http://www.baidu.com' always;
    add_header Access-Control-Allow-Credentials 'true' always; 
    add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS' always;
    add_header Access-Control-Allow-Headers 'Keep-Alive,User-Agent,Cache-Control,Content-Type,Authorization,sbid' always;  
    root /home/wwwroot/php/;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME           $document_root$fastcgi_script_name;
    include fastcgi_params;
  }  
}

server {
  listen       80;
  server_name  www.baidu.com;

  #charset koi8-r;
  #access_log  /var/log/nginx/host.access.log  main;

  location / {
    root   /home/wwwroot/view;
    try_files $uri $uri/ /index.html;
  }  
}
Was this page helpful?
0 / 5 - 0 ratings