前言
项目中遇到了一个问题,如下,看起来像是跨域问题,但是实际上在服务端设置了Access-Control-Allow-Origin *
,并且之前是一直用的好好的,但是这次重新封装了一下请求,就不行了。
Access to fetch at '***' from origin '***' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
查找问题
是请求头设置错误,导致无法跨域的问题,文档如下,大意就是 json 模式下 fetch 是默认cors模式的。即使设置成刚才代码里写的 no-cors 也会被改为 cors,applocation/json 模式下 fetch 无法跨域请求
之前使用的content-type
是form-data
,现在是application/json
根本原因:服务端的OPTIONS请求预检失败了所以会报错
之前使用的是form-data
的方式请求,属于简单请求,但是使用json
之后就变成了复杂请求
并且使用fetch的话,在使用no-cors
模式下,只能用form-data
/x-www-form-urlencoded
/text/plain
这几个方式
解决方案
在服务端进行修改,允许放行所有OPOTIONS
请求,并且把所有的跨域设置都打开
在nginx配置中增加如下
if ($request_method = 'OPTIONS') {
return 200;
}
保存刷新之后即可解决问题了
补充知识点
-
什么数据简单请求,什么是复杂请求
同时满足下面所有条件的请求为简单请求,否则为复杂请求
-
请求方式之只能是:GET/POST/HEAD
-
HTTP请求头限制以下几种字段,不能认为设置该集合外的其他字段
- Accept
- Accept-Language
- Content-Language
- Content-Type(需要注意额外的限制)
- DPR
- Downlink
- Save-Data
- Viewport-Width
-
Content-type只能够选择
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
-
请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件监听器;XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问
-
请求中没有使用 ReadableStream 对象。
经常发生的导致变为复杂请求的
- 请求的方法不是:GET/POST/HEAD,而是使用PUT/DELETE等
- POST请求的Content-Type并非
application/x-www-form-urlencoded
/multipart/form-data
/text/plain
-
-
复杂请求介绍
浏览器对于复杂跨域请求在真正发送请求之前,会先进行一次
预请求
,就是参数为OPTION
的第一次请求,他的作用是用于试探性的向服务器响应是否正确,即是否能够接受真正的请求,如果在options请求之后获取到的响应是拒绝性质的(非2xx
),那么他就会停滞第二次的真正请求的访问