okhttp 여행(8) -- CallServerInterceptor 요청 서버 차단기

5374 단어
시스템 학습 상세 보기 OKhttp 원본 해석 상세 시리즈
  • 이것은 체인 중의 마지막 차단기다.그것은 서버에 대해 네트워크 요청을 할 것이다
  • 우리는 ConnectInterceptor를 통해 서버에 연결되었습니다. 다음은 요청 데이터를 쓰고 되돌아오는 데이터를 읽는 것입니다.전체 프로세스:
  • 요청 헤더를 기록합니다
  • 요청체에 쓰기
  • 응답 헤더를 읽습니다
  • 응답체를 읽습니다
  • public final class CallServerInterceptor implements Interceptor 
        @Override
        public Response intercept(Chain chain) throws IOException {
            // Interceptor 
            RealInterceptorChain realChain = (RealInterceptorChain) chain;
            HttpCodec httpCodec = realChain.httpStream();
            StreamAllocation streamAllocation = realChain.streamAllocation();
            RealConnection connection = (RealConnection) realChain.connection();
            Request request = realChain.request();
    
            long sentRequestMillis = System.currentTimeMillis();
            //1.  
            realChain.eventListener().requestHeadersStart(realChain.call());
            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.
                // “Expect:100-continue” , “HTTP / 1.1 100 Continue” 。
                //  , ( 4xx ), 。
                if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
                    httpCodec.flushRequest();
                    realChain.eventListener().responseHeadersStart(realChain.call());
                    responseBuilder = httpCodec.readResponseHeaders(true);
                }
                //2  
                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);
    
                    request.body().writeTo(bufferedRequestBody);
                    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();
                }
            }
    
            httpCodec.finishRequest();
    
            if (responseBuilder == null) {
                realChain.eventListener().responseHeadersStart(realChain.call());
                responseBuilder = httpCodec.readResponseHeaders(false);
            }
    
            Response response = responseBuilder
                    .request(request)
                    .handshake(streamAllocation.connection().handshake())
                    .sentRequestAtMillis(sentRequestMillis)
                    .receivedResponseAtMillis(System.currentTimeMillis())
                    .build();
            //4  
            int code = response.code();
            if (code == 100) {
                // server sent a 100-continue even though we did not request one.
                // try again to read the actual response
                responseBuilder = httpCodec.readResponseHeaders(false);
    
                response = responseBuilder
                        .request(request)
                        .handshake(streamAllocation.connection().handshake())
                        .sentRequestAtMillis(sentRequestMillis)
                        .receivedResponseAtMillis(System.currentTimeMillis())
                        .build();
    
                code = response.code();
            }
    
            realChain.eventListener()
                    .responseHeadersEnd(realChain.call(), response);
    
            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();
            }
    
            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;
        }
    }
    

    좋은 웹페이지 즐겨찾기