阅读 273

前端简单请求&非简单请求

问题背景

Vue项目里用axios调用一个公共开放的API服务(该服务已经设置Access-Control-Allow-Origin:*)

问题表现

  • 在axios服务里面的代码(部分逻辑代码已省略)
// request.js
……
axios.defaults.withCredentials = true;
axios.defaults.crossDomain = true;
axios.interceptors.request.use(config => {
  ……
  config.headers['Authorization'] = `Basic ${Base64.encode(`${website.clientId}:${website.clientSecret}`)}`;
  config.headers[website.tokenHeader] = 'bearer ' + getToken()
  config.headers["Content-Type"] = "text/plain";
  ……
})
……
// index.js
export const getData = () => request({
  url: 'http://location.tianditu.gov.cn/data/getCityName?callback=query',
  method: 'get'
});
// index.vue
getData().then(res => {
  const data = res.data;
})
复制代码
  • 在axios服务的报错信息

image.png

  • 请求头信息

image.png

image.png

明明是开放的第三方公共API,用postman调用人家的Access-Control-Allow-Origin已经设置了*,却显示跨域的报错信息?我表示不服,于是三下五除二在当前项目引入了JQuery,用$大法发起ajax请求

$.ajax({
    type:"get",
    url:"http://location.tianditu.gov.cn/data/getCityName?callback=query",	 
    success: function(data) {
      console.log(data)
    }
  });
复制代码

image.png

初步结论

这个带些玄学色彩的接口,用JQuery大法请求是正常的,用axios请求报跨域

image.png

于是我就各种谷歌,依然毫无头绪,有些大佬也遇到过这样的问题,提出来过但是并没有给除一个完美的解释,就在我准备放弃的时候,突然不小心扫到阮一峰老师五年前的一篇跨域资源共享 CORS 详解

image.png

浏览器的两种请求

浏览器将请求分为两大类:简单请求(simple request)和非简单请求(not-so-simple request)

  • 简单请求(需要同时满足以下两大条件)

    1. 请求方法是以下三种方法之一
      • HEAD
      • GET
      • POST
    2. HTTP的头信息不超出以下几种字段:
      • Accept
      • Accept-Language
      • Content-Language
      • Last-Event-ID
      • Content-Type:只限于三个值application/x-www-form-urlencodedmultipart/form-datatext/plain
  • 非简单请求(凡是不是简单请求的,就是非简单请求)

    非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT或者DELETE,或者content-type是application/json。非简单请求会在正式通信之前,增加一次HTTP的查询请求,称为“预检”请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

哥德巴赫猜想

axios跨域是因为用axios发起了一个非简单请求,而JQuery大法只是一个简单的请求,跨域正是因为非简单请求的preflight

axios服务发起的非简单请求 1634021512(1).jpg

$.ajax发起的简单请

1634021737(1).jpg

总结

之前封装的axios服务,带来太多非必要的请求头信息,导致简单请求变成非简单请求,非简单请求又发起了了一个preflight,而该第三方服务对预检请求处理可能出了些问题,导致浏览器误认为这是一次跨域的请求

还是之前的axios服务,剔除掉冗余的header信息或者用一个new的axios,依然可以愉快的正常发起简单请求

image.png

文章分类
前端
文章标签