Summary of OkHttp source code interpretation (XIII) - > call server interceptor

Keywords: network socket OkHttp

Summary of OkHttp source code interpretation (XIII) - > call server interceptor

Tags (space separated): learning notes of OkHttp source code

Preface

  • The following summary of relevant knowledge is based on the relevant learning and opinions of mooc.com. If you need to check the relevant teaching of mooc.com, you can still feel it.

Introduction to official website

/** This is the last interceptor in the chain. It makes a network call to the server. */

1. Initiate a real network request
 2. Return the data returned by the server

Main source code

@Override public Response intercept(Chain chain) throws IOException {
    //Interceptor chain
    RealInterceptorChain realChain = (RealInterceptorChain) chain;
    //HttpCodec object source sink two objects input and output / / used to encode request decoding response 
    HttpCodec httpCodec = realChain.httpStream();
    //Other network components used to establish network requests  
    StreamAllocation streamAllocation = realChain.streamAllocation();
    //
    RealConnection connection = (RealConnection) realChain.connection();
    //Network request
    Request request = realChain.request();

    long sentRequestMillis = System.currentTimeMillis();

    realChain.eventListener().requestHeadersStart(realChain.call());
    //Write request header information to socket
    httpCodec.writeRequestHeaders(request);
    realChain.eventListener().requestHeadersEnd(realChain.call(), request);

    Response.Builder responseBuilder = null;
    if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
      // If there's a "Expect: 100-continue" header on the request, wait for a "HTTP/1.1 100
      // Continue" response before transmitting the request body. If we don't get that, return
      // what we did get (such as a 4xx response) without ever transmitting the request body.
      //Ask if the service can send information with the request body
      if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
        httpCodec.flushRequest();
        realChain.eventListener().responseHeadersStart(realChain.call());
        responseBuilder = httpCodec.readResponseHeaders(true);
      }

      if (responseBuilder == null) {
        // Write the request body if the "Expect: 100-continue" expectation was met.
        realChain.eventListener().requestBodyStart(realChain.call());
        long contentLength = request.body().contentLength();
        CountingSink requestBodyOut =
            new CountingSink(httpCodec.createRequestBody(request, contentLength));
        BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);
        //Call the request.body().writeTo() method to write the body information to the socket
        request.body().writeTo(bufferedRequestBody);
        //Close
        bufferedRequestBody.close();
        realChain.eventListener()
            .requestBodyEnd(realChain.call(), requestBodyOut.successfulCount);
      } else if (!connection.isMultiplexed()) {
        // If the "Expect: 100-continue" expectation wasn't met, prevent the HTTP/1 connection
        // from being reused. Otherwise we're still obligated to transmit the request body to
        // leave the connection in a consistent state.
        streamAllocation.noNewStreams();
      }
    }
    //Write operation of network request completed
    httpCodec.finishRequest();

    if (responseBuilder == null) {
      realChain.eventListener().responseHeadersStart(realChain.call());
      //Read response through readResponseHeaders of httpCodec
      responseBuilder = httpCodec.readResponseHeaders(false);
    }
   //Create a response object through streamalallocation request
    Response response = responseBuilder
        .request(request)
        .handshake(streamAllocation.connection().handshake())
        .sentRequestAtMillis(sentRequestMillis)
        .receivedResponseAtMillis(System.currentTimeMillis())
        .build();

    realChain.eventListener()
        .responseHeadersEnd(realChain.call(), response);
    //Get response
    int code = response.code();
    if (forWebSocket && code == 101) {
      // Connection is upgrading, but we need to ensure interceptors see a non-null response body.
      response = response.newBuilder()
          .body(Util.EMPTY_RESPONSE)
          .build();
    } else {
      //Call httpCodec.openResponseBody(response) to create a response
      response = response.newBuilder()
          .body(httpCodec.openResponseBody(response))
          .build();
    }

    if ("close".equalsIgnoreCase(response.request().header("Connection"))
        || "close".equalsIgnoreCase(response.header("Connection"))) {
      //Prevent new streams from creating closed streams and closing connection s    
      streamAllocation.noNewStreams();
    }
    //If the code is 204 or 205, an exception will be thrown
    if ((code == 204 || code == 205) && response.body().contentLength() > 0) {
      throw new ProtocolException(
          "HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength());
    }
    //Finally, return the response
    return response;
  }
  • 1. Call httpCodec.writeRequestHeaders(request) to write header information to socket object
  • 2. request.body().writeTo(bufferedRequestBody) writes body information to socket
  • 3. httpCodec.finishRequest() indicates that the writing of network request is completed
  • 4. responseBuilder = httpCodec.readResponseHeaders(false) read the header information of the network request
  • 5. Read the body information in the network request through the following code logic

    if (forWebSocket && code == 101) {
      // Connection is upgrading, but we need to ensure interceptors see a non-null response body.
      response = response.newBuilder()
          .body(Util.EMPTY_RESPONSE)
          .build();
    } else {
      response = response.newBuilder()
          .body(httpCodec.openResponseBody(response))
          .build();
    }

General situation of a network request in OkHttp

  • 1. Encapsulation of call object to request
  • 2. dispatcher distributor distributes requests
  • 3. getResponseWithInterceptors() method
    • Retryandfollowupinterceptor
    • Cacheinterceptor (CACHE)
    • Bridgeinterceptor (handles request and response objects against actual request and response Transformations / cookies)
    • Connectinterceptor (responsible for establishing intercepting and streaming objects)
    • Callserverinterceptor (completes the final network request and read response)

Posted by seansd on Sun, 19 Apr 2020 08:15:11 -0700