Envoy::StatusOr<ParserStatus> ClientConnectionImpl::onHeadersCompleteBase() {
  ENVOY_CONN_LOG(trace, "status_code {}", connection_, parser_->statusCode());

  // Handle the case where the client is closing a kept alive connection (by sending a 408
  // with a 'Connection: close' header). In this case we just let response flush out followed
  // by the remote close.
  if (!pending_response_.has_value() && !resetStreamCalled()) {
    return prematureResponseError("", static_cast<Http::Code>(parser_->statusCode()));
  } else if (pending_response_.has_value()) {
    ASSERT(!pending_response_done_);
    auto& headers = absl::get<ResponseHeaderMapPtr>(headers_or_trailers_);
    ENVOY_CONN_LOG(trace, "Client: onHeadersComplete size={}", connection_, headers->size());
    headers->setStatus(parser_->statusCode());

    if (parser_->statusCode() >= 200 && parser_->statusCode() < 300 &&
        pending_response_.value().encoder_.connectRequest()) {
      ENVOY_CONN_LOG(trace, "codec entering upgrade mode for CONNECT response.", connection_);
      handling_upgrade_ = true;
    }

    if (parser_->statusCode() < 200 || parser_->statusCode() == 204) {
      if (headers->TransferEncoding()) {
        RETURN_IF_ERROR(
            sendProtocolError(Http1ResponseCodeDetails::get().TransferEncodingNotAllowed));
        return codecProtocolError(
            "http/1.1 protocol error: transfer encoding not allowed in 1xx or 204");
      }

      if (headers->ContentLength()) {
        // Report a protocol error for non-zero Content-Length, but paper over zero Content-Length.
        if (headers->ContentLength()->value().getStringView() != "0") {
          RETURN_IF_ERROR(
              sendProtocolError(Http1ResponseCodeDetails::get().ContentLengthNotAllowed));
          return codecProtocolError(
              "http/1.1 protocol error: content length not allowed in 1xx or 204");
        }

        headers->removeContentLength();
      }
    }

    if (HeaderUtility::isSpecial1xx(*headers)) {
      pending_response_.value().decoder_->decode1xxHeaders(std::move(headers));
    } else if (cannotHaveBody() && !handling_upgrade_) {
      deferred_end_stream_headers_ = true;
    } else {
      pending_response_.value().decoder_->decodeHeaders(std::move(headers), false);
    }

    // http-parser treats 1xx headers as their own complete response. Swallow the spurious
    // onMessageComplete and continue processing for purely informational headers.
    // 101-SwitchingProtocols is exempt as all data after the header is proxied through after
    // upgrading.
    if (CodeUtility::is1xx(parser_->statusCode()) &&
        parser_->statusCode() != enumToInt(Http::Code::SwitchingProtocols)) {
      ignore_message_complete_for_1xx_ = true;
      // Reset to ensure no information from the 1xx headers is used for the response headers.
      headers_or_trailers_.emplace<ResponseHeaderMapPtr>(nullptr);
    }
  }

  // Here we deal with cases where the response cannot have a body by returning
  // ParserStatus::NoBody, but http_parser does not deal with it for us.
  return cannotHaveBody() ? ParserStatus::NoBody : ParserStatus::Success;
}
Envoy::StatusOr<ParserStatus> ClientConnectionImpl::onHeadersCompleteBase() {
  ENVOY_CONN_LOG(trace, "status_code {}", connection_, parser_->statusCode());

   
   
   
  if (!pending_response_.has_value() && !resetStreamCalled()) {
    return prematureResponseError("", static_cast<Http::Code>(parser_->statusCode()));
  } else if (pending_response_.has_value()) {
    ASSERT(!pending_response_done_);
    auto& headers = absl::get<ResponseHeaderMapPtr>(headers_or_trailers_);
    ENVOY_CONN_LOG(trace, "Client: onHeadersComplete size={}", connection_, headers->size());
    headers->setStatus(parser_->statusCode());

    if (parser_->statusCode() >= 200 && parser_->statusCode() < 300 &&
        pending_response_.value().encoder_.connectRequest()) {
      ENVOY_CONN_LOG(trace, "codec entering upgrade mode for CONNECT response.", connection_);
      handling_upgrade_ = true;
    }

    if (parser_->statusCode() < 200 || parser_->statusCode() == 204) {
      if (headers->TransferEncoding()) {
        RETURN_IF_ERROR(
            sendProtocolError(Http1ResponseCodeDetails::get().TransferEncodingNotAllowed));
        return codecProtocolError(
            "http/1.1 protocol error: transfer encoding not allowed in 1xx or 204");
      }

      if (headers->ContentLength()) {
         
        if (headers->ContentLength()->value().getStringView() != "0") {
          RETURN_IF_ERROR(
              sendProtocolError(Http1ResponseCodeDetails::get().ContentLengthNotAllowed));
          return codecProtocolError(
              "http/1.1 protocol error: content length not allowed in 1xx or 204");
        }

        headers->removeContentLength();
      }
    }

    if (HeaderUtility::isSpecial1xx(*headers)) {
      pending_response_.value().decoder_->decode1xxHeaders(std::move(headers));
    } else if (cannotHaveBody() && !handling_upgrade_) {
      deferred_end_stream_headers_ = true;
    } else {
      pending_response_.value().decoder_->decodeHeaders(std::move(headers), false);
    }

     
     
     
     
    if (CodeUtility::is1xx(parser_->statusCode()) &&
        parser_->statusCode() != enumToInt(Http::Code::SwitchingProtocols)) {
      ignore_message_complete_for_1xx_ = true;
       
      headers_or_trailers_.emplace<ResponseHeaderMapPtr>(nullptr);
    }
  }

   
   
  return cannotHaveBody() ? ParserStatus::NoBody : ParserStatus::Success;
}