美文网首页
OkHttp拦截器学习

OkHttp拦截器学习

作者: 石器时代小古董 | 来源:发表于2018-05-17 15:45 被阅读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());
      }
    

    相关文章

      网友评论

          本文标题:OkHttp拦截器学习

          本文链接:https://www.haomeiwen.com/subject/nivbdftx.html