okhttp源碼解析-http協議的實現-重定向

http協議中的重定向

client:
向server發送一個請求,要求獲取一個資源java

server:
接收到這個請求後,發現請求的這個資源實際存放在另外一個位置
因而server在返回的response header的Location字段中寫入那個請求資源的正確的URL,並設置reponse的狀態碼爲30x
client:
接收到這個response後,發現狀態碼爲重定向的狀態嗎,就會去解析到新的URL,根據新的URL從新發起請求git

狀態碼

重定向最經常使用爲301,也有303,github

臨時重定向用302,307瀏覽器

Paste_Image.png

與請求轉發的對比

請求轉發服務器

服務器在處理request的過程當中將request前後委託多個servlet或jsp接替進行處理的過程,request和reponse始終在期間傳遞網絡

  • 重定向時,客戶端發起兩次請求,而請求轉發時,客戶端只發起一次請求jsp

  • 重定向後,瀏覽器地址欄url變成第二個url,而請求轉發沒有變(請求轉發對於客戶端是透明的)ide

  • 流程ui

重定向:
用戶請求-----》服務器入口-------》組件------>服務器出口-------》用戶----(重定向)---》新的請求url

請求轉發
用戶請求-----》服務器入口-------》組件1---(轉發)----》組件2------->服務器出口-------》用戶

服務端實現

  • 重定向

response.sendRedirect()
  • 請求轉發
    在Servlet裏,實現dispatch是經過RequestDispatchers來實現的,這個類有兩個方法:forward,include

JSP裏實現dispatch的標籤也有兩個:jsp:forward和jsp:include

okhttp中的實現

邏輯

  • 讀取到響應狀態碼爲30x時,拿到重定向的url,用這個url置換掉request中的原url

  • 對request的一些header,body分狀況進行處理

  • 從新執行這個request,發出請求

代碼實現

RetryAndFollowUpInterceptor的intercept方法中構建了while (true)循環,循環內部:

1. 根據response重建request:Request followUp = followUpRequest(response)

int responseCode = userResponse.code();

而後switch (responseCode)進行判斷:

Paste_Image.png

Paste_Image.png

2.從新執行這個request:

將前一步獲得的followUp 賦值給request,從新進入循環,

@Override public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();

  ...
    while (true) {
      if (canceled) {
        streamAllocation.release();
        throw new IOException("Canceled");
      }

      Response response = null;
      boolean releaseConnection = true;
      try {
        response = ((RealInterceptorChain) chain).proceed(request, streamAllocation, null, null);//執行網絡請求
        releaseConnection = false;
     ...


      Request followUp = followUpRequest(response);//拿到重定向的request

   if (followUp == null) {
        if (!forWebSocket) {
          streamAllocation.release();
        }
        return response;//若是不是重定向,就返回response
      }

      ...
    if (++followUpCount > MAX_FOLLOW_UPS) {//有最大次數限制20次
        streamAllocation.release();
        throw new ProtocolException("Too many follow-up requests: " + followUpCount);
      }

      request = followUp;//把重定向的請求賦值給request,以便再次進入循環執行
      priorResponse = response;
    }
  }

okhttp的相關配置

重定向功能默認是開啓的,能夠選擇關閉,而後去實現本身的重定向功能:

new OkHttpClient().newBuilder()
                              .followRedirects(false)  //禁制OkHttp的重定向操做,咱們本身處理重定向
                              .followSslRedirects(false)//https的重定向也本身處理
相關文章
相關標籤/搜索