关于fetch的跨域问题调研
Pt.1 fetch基本跨域配置
fetch(resource);
fetch(resource, options);
fetch方法接受两个参数,resources与options
resources 获取资源的URL,可以是一个字符串、一个URL对象、或者一个Request对象
options 对fetch的自定义设置
在options参数中,可对headers、method、cache、keepalive等属性进行配置,一般来说,前端实现跨域,只需要将此参数的mode
属性设为'cors'
即可,当然,这也需要后端对Access-Control-Allow-Origin
相关的一系列相应标头进行配置,但那并不是前端的范畴
Pt.2 当你配置了mode='cors'却依然无法跨域
1. 普普通通的报错
Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.
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.
关键内容:
Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.
No 'Access-Control-Allow-Origin' header is present on the requested resource
以上两种报错相对常见,前者为后端未配置好Access-Control-Allow-Headers
,后者为未配置好Access-Control-Allow-Origin
需要注意的是,Access-Control-Allow-Origin
的报错中会让你set the request's mode to 'no-cors'
,即将 options.mode 选项设为 no-cors
,不要这样做,这不会解决问题
2. 稍稍有点内容的报错
关键内容:The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
翻译:当请求的凭证模式为“include”时,响应中“Access-Control-Allow-Origin”标头的值不能是通配符“*”
错误原因:options.credentials——携带资源凭证,表示用户代理是否应该在跨域请求的情况下从其他域发送 cookies,它的取值范围如下:
omit
: 从不发送 cookiessame-origin
: 只有当 URL 与响应脚本同源才发送 cookies、HTTP Basic authentication 等验证信息.(浏览器默认值,在旧版本浏览器,例如 safari 11 依旧是 omit,safari 12 已更改)include
: 不论是不是跨域的请求,总是发送请求资源域在本地的 cookies、HTTP Basic authentication 等验证信息
mdn web docs 在《使用 Fetch》一文中有注明,当请求使用credentials: 'include'
时,响应的 Access-Control-Allow-Origin
不能使用通配符 "*
",Access-Control-Allow-Origin
必须是当前请求的源
这种情况往往会在试图用fetch携带cookie时出现
fetch请求在默认情况下是不携带cookie的,无论同源还是跨域,当有携带cookie的需求时,都要配置credentials
属性,对于前后端分离开发,往往需要将其配置为'include'
以实现跨源携带cookie,在此情况下,后端一般需要设置以下响应标头:
Access-Control-Allow-Credentials:是否允许 HTTP 跨源请求携带凭据,设置为
true
Access-Control-Allow-Origin:指定该响应的资源是否被允许与给定的来源(origin)共享,设置为与请求的标头的
origin
一致即可Access-Control-Allow-Headers:指示在实际请求中可以使用哪些 HTTP 标头,比如
content-type
、authorization
Access-Control-Allow-Methods:指定在响应预检请求时访问资源所允许的一个或多个方法
以 Express 为例:
const server = express();
const cors = require("cors");
server.use(
cors({
origin: ["http://192.168.x.xx:xxxx"], // 前端服务地址
methods: ["DELETE", "PUT", "POST", "GET", "OPTIONS"],
allowedHeaders: ["content-type"],
credentials: true,
})
);
如此即可在使用credentials: 'include'
时实现跨域资源共享