前端跨域是一个老生常谈的话题,前端必备的技能,网上相关介绍及解决方案绍多如牛毛,作者限于学识也讲不出太过深入的见解,故此本文只是记录一次解决跨域的post请求的小文,如果能帮助遇到相同问题的朋友,那也是极好的。行文或有错漏,欢迎指正。
一.背景介绍
本人写的一个vue仿猫眼电影个人练手小项目,使用的猫眼线上的api接口,使用本地代理开发时毫无异常,之后部署上线,为了解决跨域问题,我使用了nginx反向代理转发对猫眼api的请求,大部分接口没问题,但是有个post的请求接口被浏览器block了,如下图所示的红果果报错(线上bug已修复,当时没有保存截图,下图是本地模拟的bug)
对此的常规解决方案当然就是输入问题,google一番了,在一堆搜索结果中找寻要找的那个解决方案。 如果google一下立马有了解决方案,那当然是不可能的,作者也不会专门写下此文。
二.解决思路
过程是曲折的,有了此文,那么结果当然是完美解决了。
1.初步认识
虽然作者的英文很渣,但是报错的原因看几个关键词也能猜出是跨域出了问题,具体的原因嘛,是因为预请求没有通过控制访问检查,更具体的原因是预请求不允许重定向。
关键词 preflight request
对此我是懵逼的,当然解决bug的过程,也是学习的过程,我便踏上了搜罗相关文档了解preflight request是何方神圣。
2.查找文档
为什么跨域的post请求区分为简单请求和非简单请求和content-type相关?
前端 | 浅谈preflight request 是从简书上找到的对preflight request的科普文档,感兴趣的朋友可以去看看,感谢此文的作者。
阅读了前面提到的前端 | 浅谈preflight request一文,针对出现此类的bug,我试着提取了几个关键点
2.1为什么要发预检请求
preflight request是为确保服务器是否允许发起对服务器数据产生副作用的HTTP请求方法,而预先由浏览器发起OPTIONS方法的一个预检请求,如果允许就发送真实的请求,如果不允许则直接拒绝发起真实请求。
2.2首先介绍不会触发预检请求的方法
- GET
- HEAD
- POST
仅当POST方法的Content-Type值等于下列之一才算做简单需求
- text/plain
- multipart/form-data
- application/x-www-form-urlencoded
2.3触发预检请求的方法
简单起见,我们姑且认为除了上述罗列的不会触发预检请求的情况,其他情况下都会预先发送OPTIONS进行预请求。
preflight request不允许重定向
get post head当header有自定义属性时也会发送options,详见文末后记
三.尝试解决
上面铺垫分析了这么多,我们来看看错误请求头,如下图,post触发了浏览器发送预检请求OPTIONS方法,而返回的是重定向状态码是302,和上图报错信息及preflight request相关解释完全对应,那么答案就很明确了,因为我们这里使用了axios,而axios的post方法Content-Type默认是application/json; charset=utf-8;所以如何避免post触发预检请求的关键就是使用上述Content-Type的三个任一值,application/x-www-form-urlencoded才是最大淫家。
行文至此,差不多也解决了,饶了那么大一圈,就只需修改一行配置参数,是不是有种想撞墙的感觉?初次写文感觉词穷了,考虑不周或者需要补充的地方,欢迎大家提出来探讨一下。
后记补充
1. 经@摔炮指点补充:get post head当header有自定义属性时也会发送options
本着求实的态度,我进行了测试,自定义了属性 'X-GET-PREFILGHT_TEST': 'check preflight by customize headers Attributes',确实如@摔炮所言,get到了新姿势,感谢。 报错信息及请求头等信息如下: