axios发送两次请求缘由及解决方法

原文地址html


最近Vue项目中使用axios组件,在页面交互中发现axios会发送两次请求,一种请求方式为OPTIONS,另一种为本身设置的。java

 

如图:

 

 

  

什么是CORS通讯?

  CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。 它容许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。ios

  CORS须要浏览器和服务器同时支持。目前,全部浏览器都支持该功能,IE浏览器不能低于IE10。git

  实现CORS通讯的关键是服务器。只要服务器实现了CORS接口,就能够跨域通讯。详情见:先后分离调用API接口跨域问题web

 

CORS两种请求

  浏览器将CORS请求分红两类:简单请求(simple request)和非简单请求(not-so-simple request)。spring

  只要同时知足如下两大条件,就属于简单请求。json

(1) 请求方法是如下三种方法之一:axios

  • HEAD
  • GET
  • POST

(2)HTTP的头信息不超出如下几种字段:后端

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type:只限于三个值application/x-www-form-urlencodedmultipart/form-datatext/plain

  凡是不一样时知足上面两个条件,就属于非简单请求。跨域

  非简单请求是那种对服务器有特殊要求的请求,好比请求方法是PUTDELETE,或者Content-Type字段的类型是application/json

  非简单请求的CORS请求,会在正式通讯以前,增长一次HTTP查询请求,称为"预检"请求(preflight)。

  浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可使用哪些HTTP动词和头信息字段。只有获得确定答复,浏览器才会发出正式的XMLHttpRequest请求,不然就报错。

  浏览器对这两种请求的处理,是不同的。

  

 

两次请求缘由

  先后端未知足“同源策略/SOP”,俗称请求跨域。浏览器一旦发现请求跨域,就会使用CORS通讯,自动添加一些附加的头信息,简单请求只会有一次请求,只有非简单请求会附加一次请求。

 

解决方法

  服务期端直接经过“预检”请求,服务器新建拦截器,拦截全部请求,筛选全部Requset Method:OPTIONS的请求,不作任何处理直接返回便可。

  

如下是JAVA设置:

package com.yhzy.zytx.jwt.Interceptor;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * @ClassName JwtInterceptor
 * @Description JWT拦截器
 * @Author 天生傲骨、怎能屈服
 * @Date 2019/5/22 13:48
 * @Version 1.0
 */
public class JwtInterceptor implements HandlerInterceptor {
    

    private final static Logger logger = LoggerFactory.getLogger(JwtInterceptor.class);

    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
        // 从 http 请求头中取出 token
        String token = httpServletRequest.getHeader("Authorization");

        // 若是不是映射到方法直接经过
        if(!(object instanceof HandlerMethod)){
            return true;
        }
        HandlerMethod handlerMethod=(HandlerMethod)object;
        Method method=handlerMethod.getMethod();

        // OPTIONS请求类型直接返回不处理
        if ("OPTIONS".equals(httpServletRequest.getMethod())){
            return false;
        }
        
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest,
                           HttpServletResponse httpServletResponse,
                           Object o, ModelAndView modelAndView) throws Exception {

    }
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest,
                                HttpServletResponse httpServletResponse,
                                Object o, Exception e) throws Exception {
    }
}

返回目录

相关文章
相关标签/搜索