- 列举 CORS 的头信息,并说明作用
- 写一段代码让 CORS 跨域请求带上 cookie
- 写一段让 http 请求失败后重试的代码
启动客户端
client> http-server // 启动客户端,默认127.0.0.1:8080
// 需要自行安装http-server等任意web静态资源服务器
启动服务端
server> npm run dev // 启动服务端,默认127.0.0.1:3000
// 需要自行安装nodejs
Devtool - network面板 - throttling的使用:
- 使用fast 3g,观察loading状态
- 使用offline,观察断网重连
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS
- cors是标准,jsonp是hack技术
- jsonp是资源的请求,请求方式局限。本地需要写接收和发送资源的逻辑。
- cors是数据请求(xhr or fetch),请求方式自由。使用xhr和fetch发送和接收数据。
- 兼容问题
- jsonp没有兼容问题
- cors需要ie10以上(不过这已经不是问题)
- 安全问题
- jsonp返回的是一个自执行函数,需要对接口提供方足够的信任。安全等级较高的业务无法使用这种方式。
/* http request 请求头 */
决定了是简单请求还是非简单请求。
问题:只要跨域,devtool-network-headers-request中看到的一定是`Provisional headers are shown`吗?
/* 使用XMLHttpRequest的说明 */
xhr.withCredentials:true // 带上凭证
/* 使用fetch的options说明 */
credentials: "include", // include, same-origin, *omit
// 不写headers时,默认只包含简单请求相关字段
// 自定义headers时注意,一旦添加了非简单请求字段或值,会多出一个options预检请求
headers: { "x-my-magic": 1,"x-your-romantic":2 }
mode: "cors" // no-cors, *cors, same-origin
/* http response 响应头 */
决定了是否支持cors响应
/* 使用nodejs添加响应头的说明 */
res.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:8080"); // 只能写一个key和一个value,可以直接从req里取并填入,不要写成*(请求凭证会无效)
res.setHeader("Access-Control-Allow-Methods", "GET,POST"); // 允许的方法(不建议开放危险方法,比如会让数据减少和删除的。)
res.setHeader(
"Access-Control-Allow-Headers",
"DNT,Origin,Referer,User-Agent,content-type,cookie,x-my-magic"
); // 给预检请求使用的headers字段
res.setHeader("Access-Control-Allow-Credentials", true); // 允许请求凭证
简单请求和非简单请求,是客户端(浏览器)的内部判断逻辑。
如果浏览器判断该请求为简单请求,则直接从js发出请求开始,直达目标服务器进行请求。
如果浏览器判断该请求为非简单请求,浏览器暂扣下该请求,由浏览器发送一个预检请求(method:options)到目标服务器。然后浏览器拿着返回的Access-Control-Allow-Headers字段和Access-Control-Allow-Methods字段进行检查,看是否与扣下的请求头相匹配。若请求头匹配(服务端支持)则请求放行,否则取消请求。
符合以下所有条件的为简单请求,否则就是非简单请求:
- 方法限制
- GET 获取实体
- POST 修改实体
- HEAD 获取头信息
- 头信息字段限制,且不能自定义值:
- Accept
- Accept-Language
- Content-Language
- Content-Type (有特殊要求)
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Width
- Content-Type限制
- text/plain
- multipart/form-data
- application/x-www-form-urlencoded
- XMLHttpRequestUpload 对象没有设置监听器
- ReadableStream 对象没有被使用到
当 http 请求无响应或者返回错误状态码(超出(200 ~ 299 && 304))时,客户端需要自动对该请求进行重新连接。
要求做到:
- 尽可能第一时间获取远端数据,恢复状态。
- 尽可能不对服务器造成持续压力,比如每次重连的请求时间翻番,以及设定最大请求数量
设定初始请求延时,比如 1 秒。
设定每一轮请求的递进延时,比如第二轮翻一番 2 秒,以此类推。
设定最大请求数量,比如 3 次。
/* 重连方法 */
function retry(handler,option) {
let count = 0;
let timeid = null;
const maxCount = option.maxCount || 3;
const ms = option.seconds*1000 || 1000;
function next(cb) {
clearTimeout(timeid);
if (count >= maxCount) {
cb();
return;
}
// 将next作为参数传递给handler,供业务使用
timeid = setTimeout(handler, ms * count, next);
count++;
}
next(null);
}
/* 应用重连逻辑 */
retry(function(next) {
fetch(
url,
options
)
.then(res => res.json())
.then(json => {
Notify.show("fetch请求成功!");
})
.catch(err => {
// 进行下一轮请求
next(() => {
Notify.show("ajax请求失败!");
});
});
},
// 配置重连策略
{
maxCount:5,
seconds:0.5
};