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-urlencoded
、multipart/form-data
、text/plain
凡是不同時滿足上面兩個條件,就屬於非簡單請求。
非簡單請求是那種對服務器有特殊要求的請求,比如請求方法是PUT
或DELETE
,或者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 !