The source code in this article is based on OkHttp 3.6.0

  • OkHttp Request Execution Process
  • Okhttp-interceptors (1)
  • Okhttp-interceptors (2)
  • Okhttp-interceptors (3)
  • Okhttp-interceptors (4)

This article analyzes the last Interceptor node in the OkHttp request flow, CallServerInterceptor. Its task is to initiate the final request to the server, complete the writing request, and read the response. ####- CallServerInterceptor Take a look at the request execution entry Intercept function.

public Response intercept(Chain chain) throws IOException {
  HttpCodec httpCodec = ((RealInterceptorChain) chain).httpStream();
  StreamAllocation streamAllocation = ((RealInterceptorChain) chain).streamAllocation();
  Request request = chain.request();

  long sentRequestMillis = System.currentTimeMillis();
  // Write the request Header
  httpCodec.writeRequestHeaders(request);

  Response.Builder responseBuilder = null;
  // If requested to be allowed to carry Body, write Body
  if(HttpMethod.permitsRequestBody(request.method()) && request.body() ! =null) {
    // If the request Header contains "Expect: 100-continue ", the client expects the server to tell it whether it is allowed to carry the Body,
    If the server returns a status code of 100, the request body is allowed to be carried, and readResponseHeaders returns NULL.
    if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
    // Flush the buffer to execute the request
      httpCodec.flushRequest();
      responseBuilder = httpCodec.readResponseHeaders(true);
    }

    // Write the request Body
    if (responseBuilder == null) { Sink requestBodyOut = httpCodec.createRequestBody(request, request.body().contentLength()); BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut); request.body().writeTo(bufferedRequestBody); bufferedRequestBody.close(); }}// Flush the buffer to execute the request
  httpCodec.finishRequest();

  // Read the response Header,
  if (responseBuilder == null) {
    responseBuilder = httpCodec.readResponseHeaders(false);
  }

  // Create a response
  Response response = responseBuilder
      .request(request)
      .handshake(streamAllocation.connection().handshake())
      .sentRequestAtMillis(sentRequestMillis)
      .receivedResponseAtMillis(System.currentTimeMillis())
      .build();

  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 {
    // Write the response Body
    response = response.newBuilder()
        .body(httpCodec.openResponseBody(response))
        .build();
  }

  // If "Connection:close" is set in the Header, the Connection is closed
  if ("close".equalsIgnoreCase(response.request().header("Connection"))
      || "close".equalsIgnoreCase(response.header("Connection"))) {
    streamAllocation.noNewStreams();
  }

  if ((code == 204 || code == 205) && response.body().contentLength() > 0) {
    throw new ProtocolException(
        "HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength());
  }

  return response;
}
Copy the code

The CallServerInterceptor executes the request in four main steps, using the HttpCodec created in the previous node to interact with the server:

  1. Request Header;
  2. Request Body;
  3. Read Response Header;
  4. Read the Response Body.

At this point, the upstream part of the Request process is finished, and an original Response is created. This Response will be returned step by step to the previous Interceptor node along the reverse path of the Request chain, so that it can continue processing the Response returned from the server. Until finally returned to the user to complete a network request.