OkHttp拦截器学习

2018-05-17  本文已影响0人  石器时代小古董

一、各个拦截器的作用

1.RetryAndFollowUpInterceptor负责对失败的链接在合适的情况下进行重定向
2.BridgeInterceptor负责构建客户端请求为服务器需要的格式
3.CacheInterceptor负责读取缓存中的请求

二、RetryAndFollowUpInterceptor

1.将请求路径封装成streamAllocation
2.proceed会执行后续拦截器实现真正的网络请求,如果异常,会通过recover检查是否可以恢复
3.followup方法接收服务端的响应后检查是否满足重定向的需求
4.如果满足会重新根据返回的请求解析出url,重新构建一个请求包装成streamAllocation,满足重定向的错误码(300,301,302,303)

while (true) {
.....
      Response response = null;
      boolean releaseConnection = true;
      try {
        response = ((RealInterceptorChain) chain).proceed(request, streamAllocation, null, null);
        releaseConnection = false;
      }
  ..... 
    catch (IOException e) {
        // An attempt to communicate with a server failed. The request may have been sent.
        boolean requestSendStarted = !(e instanceof ConnectionShutdownException);
        if (!recover(e, requestSendStarted, request)) throw e;
        releaseConnection = false;
        continue;
      } finally {
        // We're throwing an unchecked exception. Release any resources.
        if (releaseConnection) {
          streamAllocation.streamFailed(null);
          streamAllocation.release();
        }
      }

      // Attach the prior response if it exists. Such responses never have a body.
      if (priorResponse != null) {
        response = response.newBuilder()
            .priorResponse(priorResponse.newBuilder()
                    .body(null)
                    .build())
            .build();
      }
     //检查是否需要重定向
      Request followUp = followUpRequest(response);

      if (followUp == null) {
        if (!forWebSocket) {
          streamAllocation.release();
        }
        return response;
      }

      closeQuietly(response.body());
     //重定向的次数不能超过20次
      if (++followUpCount > MAX_FOLLOW_UPS) {
        streamAllocation.release();
        throw new ProtocolException("Too many follow-up requests: " + followUpCount);
      }

      if (followUp.body() instanceof UnrepeatableRequestBody) {
        streamAllocation.release();
        throw new HttpRetryException("Cannot retry streamed HTTP body", response.code());
      }
     //确保构建出来的不是同一个connect,再次请求一遍同样的connect仍然会失败
      if (!sameConnection(response, followUp.url())) {
        streamAllocation.release();
        streamAllocation = new StreamAllocation(
            client.connectionPool(), createAddress(followUp.url()), callStackTrace);
      } else if (streamAllocation.codec() != null) {
        throw new IllegalStateException("Closing the body of " + response
            + " didn't close its backing stream. Bad interceptor?");
      }
      request = followUp;
      priorResponse = response;
    }
  }

根据端口,协议,路径来判断是否为同一个请求

  //scheme:http或https
  private boolean sameConnection(Response response, HttpUrl followUp) {
    HttpUrl url = response.request().url();
    return url.host().equals(followUp.host())
        && url.port() == followUp.port()
        && url.scheme().equals(followUp.scheme());
  }
上一篇下一篇

猜你喜欢

热点阅读