记一次跨域post请求数据之preflight request

5,136 阅读4分钟

前端跨域是一个老生常谈的话题,前端必备的技能,网上相关介绍及解决方案绍多如牛毛,作者限于学识也讲不出太过深入的见解,故此本文只是记录一次解决跨域的post请求的小文,如果能帮助遇到相同问题的朋友,那也是极好的。行文或有错漏,欢迎指正。

一.背景介绍

本人写的一个vue仿猫眼电影个人练手小项目,使用的猫眼线上的api接口,使用本地代理开发时毫无异常,之后部署上线,为了解决跨域问题,我使用了nginx反向代理转发对猫眼api的请求,大部分接口没问题,但是有个post的请求接口被浏览器block了,如下图所示的红果果报错(线上bug已修复,当时没有保存截图,下图是本地模拟的bug)

error

对此的常规解决方案当然就是输入问题,google一番了,在一堆搜索结果中找寻要找的那个解决方案。 如果google一下立马有了解决方案,那当然是不可能的,作者也不会专门写下此文。

二.解决思路

过程是曲折的,有了此文,那么结果当然是完美解决了。

1.初步认识

虽然作者的英文很渣,但是报错的原因看几个关键词也能猜出是跨域出了问题,具体的原因嘛,是因为预请求没有通过控制访问检查,更具体的原因是预请求不允许重定向。

关键词 preflight request

对此我是懵逼的,当然解决bug的过程,也是学习的过程,我便踏上了搜罗相关文档了解preflight request是何方神圣。

2.查找文档

重定向 CORS 跨域请求

为什么跨域的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才是最大淫家。

http_headers

行文至此,差不多也解决了,饶了那么大一圈,就只需修改一行配置参数,是不是有种想撞墙的感觉?初次写文感觉词穷了,考虑不周或者需要补充的地方,欢迎大家提出来探讨一下。

后记补充

1. 经@摔炮指点补充:get post head当header有自定义属性时也会发送options

本着求实的态度,我进行了测试,自定义了属性 'X-GET-PREFILGHT_TEST': 'check preflight by customize headers Attributes',确实如@摔炮所言,get到了新姿势,感谢。 报错信息及请求头等信息如下:

error
headers