axios發送兩次請求原因及解決方法


axios發送兩次請求原因及解決方法

 

最近Vue項目中使用axios組件,在頁面交互中發現axios會發送兩次請求,一種請求方式為OPTIONS,另外一種為自己設置的。

 

如圖:

 

 

  

什么是CORS通信?

  CORS是一個W3C標准,全稱是"跨域資源共享"(Cross-origin resource sharing)。 它允許瀏覽器向跨源服務器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。

  CORS需要瀏覽器和服務器同時支持。目前,所有瀏覽器都支持該功能,IE瀏覽器不能低於IE10。

  實現CORS通信的關鍵是服務器。只要服務器實現了CORS接口,就可以跨域通信。詳情見:前后分離調用API接口跨域問題

 

CORS兩種請求

  瀏覽器將CORS請求分成兩類:簡單請求(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

  凡是不同時滿足上面兩個條件,就屬於非簡單請求。

  非簡單請求是那種對服務器有特殊要求的請求,比如請求方法是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 {
    }
}

 

完結

希望可以幫到大家,xxxx !


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM