Skip to content

解决 Axios 额外发起一次 OPTIONS 请求

Published: at 03:11 AMSuggest Changes

昨天,群里的一位群友 资深全栈开发 无霜 讨论了这个问题,我就想起来我平时也经常遇到这样的现象,但是我忽略了,今天 Mark 一下。

有时候,前端明明只发起了一次 post 请求,但是后端却会收到 2 次请求,其中一个是 option 请求

原因

跨域分为简单跨域请求复杂跨域请求

简单跨域请求是不会发送 OPTIONS 的,请求的复杂跨域请求才会发送一个预检请求 OPTIONS

复杂跨域请求要满足以下:

  1. 请求方式不是 GETPOSTHEAD
  2. POST 请求的 Content-Type 并非 application/x-www-form-urlencoded, multipart/form-data, 或 text/plain
  3. 请求设置了自定义 header 字段

解决方法

如果不想发送 option 请求可以改为简单请求 比如你的 Content-Type 可能是 application/json 格式,将其改为 application/x-www-form-urlencoded

  1. 不设置自定义请求头
  2. Content-Type 设置为 application/x-www-form-urlencoded
axios.defaults.headers.post["Content-Type"] =
  "application/x-www-form-urlencoded";
  1. 把 json 格式的 data 参数用 qs 序列化成字符串;
import axios from "axios";
import config from "@/config";
import * as util from "utils/common";
import qs from "querystring";
let localUser = util.session("token");
axios.defaults.headers.post["Content-Type"] =
  "application/x-www-form-urlencoded";
const instance = axios.create({
  timeout: config.timer.connTimeout * 1000,
  // 返回数据类型
  responseType: "json",
  // 表明是否有跨域请求
  withCredentials: false,
});

//添加请求拦截器
instance.interceptors.request.use(
  function (config) {
    // 在发送请求之前做些什么
    let data = config.data;
    if (data) {
      localUser && localUser.token && (data.token = localUser.token);
    }
    let request = {};
    request.jsondata = JSON.stringify(data);
    request = qs.stringify(request);
    config.data = request;
    return config;
  },
  function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  }
);

// 错误处理
instance.interceptors.response.use(
  function (response) {
    return response;
  },
  function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
  }
);

export default instance;
  1. 其实我们没有必要去避免 OPTIONS 请求,在实际项目中未必都是简单请求,也不是所有预检请求都可以转为简单请求,只需要后台配合设置一下跨域响应头部就可以解决了。
response.addHeader("Access-Control-Allow-Origin", "\*");
response.addHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,PUT,DELETE");
response.setHeader(“Access-Control-Allow-Headers,x-requested-with,Authorization, Content-Type”);
  1. 减少检查频率(方法由**资深全栈架构师 ZJINH**提供)
header( ' Access-Control-Max-Age', '600'); //10 分钟检查一次

部分来源

备注

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS


Previous Post
JS ESLint 配置笔记
Next Post
JS 的 call、bind、apply 笔记