前端跨域是一个老生常谈的话题, 前端必备的技能, 网上相关介绍及解决方案绍多如牛毛, 作者限于学识也讲不出太过深入的见解, 故此本文只是记录一次解决跨域的 post 请求的小文, 如果能帮助遇到相同问题的朋友, 那也是极好的. 行文或有错漏, 欢迎指正.
一. 背景介绍
本人写的一个 vue 仿猫眼电影 https://github.com/huaianfox/vue-maoyan 个人练手小项目, 使用的猫眼线上的 API 接口, 使用本地代理开发时毫无异常, 之后部署上线, 为了解决跨域问题, 我使用了 nginx 反向代理转发对猫眼 API 的请求, 大部分接口没问题, 但是有个 post 的请求接口被浏览器 block 了, 如下图所示的红果果报错 (线上 bug 已修复, 当时没有保存截图, 下图是本地模拟的 bug)
对此的常规解决方案当然就是输入问题, google 一番了, 在一堆搜索结果中找寻要找的那个解决方案. 如果 google 一下立马有了解决方案, 那当然是不可能的, 作者也不会专门写下此文.
二. 解决思路
过程是曲折的, 有了此文, 那么结果当然是完美解决了.
1. 初步认识
虽然作者的英文很渣, 但是报错的原因看几个关键词也能猜出是跨域出了问题, 具体的原因嘛, 是因为预请求没有通过控制访问检查, 更具体的原因是预请求不允许重定向.
关键词 preflight request
对此我是懵逼的, 当然解决 bug 的过程, 也是学习的过程, 我便踏上了搜罗相关文档了解 preflight request 是何方神圣.
2. 查找文档
重定向 CORS 跨域请求 https://harttle.land/2016/12/30/cors-redirect.html
前端 | 浅谈 preflight request https://www.jianshu.com/p/b55086cbd9af 是从简书上找到的对 preflight request 的科普文档, 感兴趣的朋友可以去看看, 感谢此文的作者.
阅读了前面提到的前端 | 浅谈 preflight request https://www.jianshu.com/p/b55086cbd9af 一文, 针对出现此类的 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 不允许重定向
三. 尝试解决
上面铺垫分析了这么多, 我们来看看错误请求头, 如下图, post 触发了浏览器发送预检请求 OPTIONS 方法, 而返回的是重定向状态码是 302, 和上图报错信息及 preflight request 相关解释完全对应, 那么答案就很明确了, 因为我们这里使用了 axios, 而 axios 的 post 方法 Content-Type 默认是 application/JSON; charset=utf-8; 所以如何避免 post 触发预检请求的关键就是使用上述 Content-Type 的三个任一值, application/x-www-form-urlencoded 才是最大淫家.
行文至此, 差不多也解决了, 饶了那么大一圈, 就只需修改一行配置参数, 是不是有种想撞墙的感觉? 初次写文感觉词穷了, 考虑不周或者需要补充的地方, 欢迎大家提出来探讨一下.
来源: https://juejin.im/post/5c7fd238e51d45386c5335f1