Fetch . Request
作者:杨彩清(追求极致,热爱技术和生活的95后)
本文讲述如何使用 fetch 下的 request 方法的 mode 属性值 no-cors 消除本地开发过程中跨域的错误提示,以及开发中遇到的SameSite Cookie问题及其解决方法。
遇到的问题
A 系统是以嵌入 JS 脚本的方式在B系统下工作的。A 系统的埋点需要设置一些和个人信息有关的公共字段,这些字段需要通过访问 B 系统的后端接口拿到,而本地开发调试的过程中域名为 localhost ,导致调试过程中存在跨域的问题,控制台一直有红色 Error 。
解决思路
1. 使用 webpackdevServer 代理
通过 http-proxy 代理请求。
问题:
- 需要增加额外的webpackdevServer的配置,其他的代理都针对有相对固定路径的api,代理到mock调试地址或者测试环境地址。单独的为个别接口增加代理设置不算是一个好的解决方案,可扩展性也不好。
- 并且webpackdevServer代理到B系统过程还会重定向到登录页
2. 区分开发线上环境来执行请求
if (isDev) {
//不执行埋点的请求
} else {
// 执行请求
}
问题:
发布到B-test测试环境时,还是会有跨域到B后端接口的报错;
不过本地开发看不到红色错误警告了,相对而言可接受
3. 使用Request的mode参数控制跨域的处理
禁掉跨域的请求,只在同域的情况下发请求。
知识点
Request是fetch下的一个api,一般很少会显式的用到
// 一般情况下使用fetch
fetch('url', {
//config
}).then...
// 使用request的情况下使用fetch
const request = new Request('url', {
//config
})
fetch(request)...
Request下有一些参数,也就是上面代码块的config可以配置的参数,包括cache、 credentials、headers等等,重点用到的参数是mode。
mode: {'same-origin', 'no-cors', 'cors', ...} 设置跨域请求响应是否有效
- same-origin 要求必须同源,否则抛出错误, network没有请求发出
- cors 允许跨域请求发出,响应是否可用依赖服务端设置, network有请求发出
- no-cors 跨域请求不会发送,无法读取response,network没有请求发出
浏览器兼容性:chrome浏览器基本都支持,其他浏览器可参考https://developer.mozilla.org...
关于SameSite Cookie
Chrome 80 在 2020 年 2 月后把 cookie 的 same-site 属性默认设置从 None 改为 Lax ,对一些系统之间需要相互嵌入且需要同步 cookie 的场景造成了影响;短期的办法可以通过更改浏览器设置来处理。
SameSite Cookie
- SameSite = None
允许cross-site的Request携带3rd-party Cookie,这样在C系统嵌入(例如使用iframe)其他D系统的页面,登录后可以正常访问把cookie带到对D的request上,可以正常访问。
- SameSite = Lax
不允许cross-site的Request携带3rd-party Cookie,这样导致无法在C系统直接访问内嵌的D系统;但是通过a,link等顶层的链接是可以携带3rd-party Cookie的。
- SameSite = strict
不允许cross-site的Request携带3rd-party Cookie;通过a, link等顶层链接也无法携带Cookie
问题背景
- C系统内有一些iframe内嵌了D系统(一款在线文档编辑系统)的文档,最近有个别用户反馈在C里没有权限查看内嵌的文档,一直跳转到D系统的登录页面,重复登录也不管用,点击链接跳转到浏览器打开才能正常使用。
- 排查过程中发现
解决方法
短期:chrome设置中关闭把默认的cookie 的 sameSite 设置为lax的设置
长期:前后端完成对cookie的改造,显示的声明会在cross-site场景使用到的cookie的SameSite属性值,针对
参考链接:
招聘
字节跳动商业化前端团队招人啦!可以每日与技术网红畅谈理想、参加技术大牛交流分享、享受一日四餐、顶级极客装备、免费健身房,与优秀的人做有挑战的事情,这种地方哪里找?快来加入我们吧!
简历投递邮箱: sunyunchao@bytedance.com
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。