Factor the header validation and response-code parsing/validation code in QuicSpdyClientStream::OnInitialHeadersComplete out such that they can be overriden in subclasses.

PiperOrigin-RevId: 475381192
diff --git a/quiche/quic/core/http/quic_spdy_client_stream.cc b/quiche/quic/core/http/quic_spdy_client_stream.cc
index 92277f9..1661c94 100644
--- a/quiche/quic/core/http/quic_spdy_client_stream.cc
+++ b/quiche/quic/core/http/quic_spdy_client_stream.cc
@@ -43,6 +43,49 @@
 
 QuicSpdyClientStream::~QuicSpdyClientStream() = default;
 
+bool QuicSpdyClientStream::CopyAndValidateHeaders(
+    const QuicHeaderList& header_list, int64_t& content_length,
+    spdy::Http2HeaderBlock& headers) {
+  return SpdyUtils::CopyAndValidateHeaders(header_list, &content_length,
+                                           &headers);
+}
+
+bool QuicSpdyClientStream::ParseAndValidateStatusCode() {
+  if (!ParseHeaderStatusCode(response_headers_, &response_code_)) {
+    QUIC_DLOG(ERROR) << "Received invalid response code: "
+                     << response_headers_[":status"].as_string()
+                     << " on stream " << id();
+    Reset(QUIC_BAD_APPLICATION_PAYLOAD);
+    return false;
+  }
+
+  if (response_code_ == 101) {
+    // 101 "Switching Protocols" is forbidden in HTTP/3 as per the
+    // "HTTP Upgrade" section of draft-ietf-quic-http.
+    QUIC_DLOG(ERROR) << "Received forbidden 101 response code"
+                     << " on stream " << id();
+    Reset(QUIC_BAD_APPLICATION_PAYLOAD);
+    return false;
+  }
+
+  if (response_code_ >= 100 && response_code_ < 200) {
+    // These are Informational 1xx headers, not the actual response headers.
+    QUIC_DLOG(INFO) << "Received informational response code: "
+                    << response_headers_[":status"].as_string() << " on stream "
+                    << id();
+    set_headers_decompressed(false);
+    if (response_code_ == 100 && !has_preliminary_headers_) {
+      // This is 100 Continue, save it to enable "Expect: 100-continue".
+      has_preliminary_headers_ = true;
+      preliminary_headers_ = std::move(response_headers_);
+    } else {
+      response_headers_.clear();
+    }
+  }
+
+  return true;
+}
+
 void QuicSpdyClientStream::OnInitialHeadersComplete(
     bool fin, size_t frame_len, const QuicHeaderList& header_list) {
   QuicSpdyStream::OnInitialHeadersComplete(fin, frame_len, header_list);
@@ -55,8 +98,8 @@
     return;
   }
 
-  if (!SpdyUtils::CopyAndValidateHeaders(header_list, &content_length_,
-                                         &response_headers_)) {
+  if (!CopyAndValidateHeaders(header_list, content_length_,
+                              response_headers_)) {
     QUIC_DLOG(ERROR) << "Failed to parse header list: "
                      << header_list.DebugString() << " on stream " << id();
     Reset(QUIC_BAD_APPLICATION_PAYLOAD);
@@ -77,38 +120,10 @@
     }
   }
 
-  if (!ParseHeaderStatusCode(response_headers_, &response_code_)) {
-    QUIC_DLOG(ERROR) << "Received invalid response code: "
-                     << response_headers_[":status"].as_string()
-                     << " on stream " << id();
-    Reset(QUIC_BAD_APPLICATION_PAYLOAD);
+  if (!ParseAndValidateStatusCode()) {
     return;
   }
 
-  if (response_code_ == 101) {
-    // 101 "Switching Protocols" is forbidden in HTTP/3 as per the
-    // "HTTP Upgrade" section of draft-ietf-quic-http.
-    QUIC_DLOG(ERROR) << "Received forbidden 101 response code"
-                     << " on stream " << id();
-    Reset(QUIC_BAD_APPLICATION_PAYLOAD);
-    return;
-  }
-
-  if (response_code_ >= 100 && response_code_ < 200) {
-    // These are Informational 1xx headers, not the actual response headers.
-    QUIC_DLOG(INFO) << "Received informational response code: "
-                    << response_headers_[":status"].as_string() << " on stream "
-                    << id();
-    set_headers_decompressed(false);
-    if (response_code_ == 100 && !has_preliminary_headers_) {
-      // This is 100 Continue, save it to enable "Expect: 100-continue".
-      has_preliminary_headers_ = true;
-      preliminary_headers_ = std::move(response_headers_);
-    } else {
-      response_headers_.clear();
-    }
-  }
-
   ConsumeHeaderList();
   QUIC_DVLOG(1) << "headers complete for stream " << id();
 
diff --git a/quiche/quic/core/http/quic_spdy_client_stream.h b/quiche/quic/core/http/quic_spdy_client_stream.h
index a0806d7..7a4f90a 100644
--- a/quiche/quic/core/http/quic_spdy_client_stream.h
+++ b/quiche/quic/core/http/quic_spdy_client_stream.h
@@ -73,6 +73,16 @@
  protected:
   bool AreHeadersValid(const QuicHeaderList& header_list) const override;
 
+  // Called by OnInitialHeadersComplete to set response_header_. Returns false
+  // on error.
+  virtual bool CopyAndValidateHeaders(const QuicHeaderList& header_list,
+                                      int64_t& content_length,
+                                      spdy::Http2HeaderBlock& headers);
+
+  // Called by OnInitialHeadersComplete to set response_code_ based on
+  // response_header_. Returns false on error.
+  virtual bool ParseAndValidateStatusCode();
+
  private:
   // The parsed headers received from the server.
   spdy::Http2HeaderBlock response_headers_;
diff --git a/quiche/quic/tools/quic_simple_client_session.h b/quiche/quic/tools/quic_simple_client_session.h
index f3231ad..763a1a3 100644
--- a/quiche/quic/tools/quic_simple_client_session.h
+++ b/quiche/quic/tools/quic_simple_client_session.h
@@ -27,6 +27,7 @@
   HttpDatagramSupport LocalHttpDatagramSupport() override;
   std::unique_ptr<QuicPathValidationContext> CreateContextForMultiPortPath()
       override;
+  bool drop_response_body() const { return drop_response_body_; }
 
  private:
   QuicClientBase::NetworkHelper* network_helper_;