Allows "classic" HTTP/2 CONNECT request headers.

PiperOrigin-RevId: 450671963
diff --git a/quiche/http2/adapter/header_validator.cc b/quiche/http2/adapter/header_validator.cc
index 23d4225..972b0c6 100644
--- a/quiche/http2/adapter/header_validator.cc
+++ b/quiche/http2/adapter/header_validator.cc
@@ -81,17 +81,29 @@
 }
 
 bool ValidateRequestHeaders(const std::vector<std::string>& pseudo_headers,
+                            absl::optional<std::string>& authority,
                             absl::string_view method, absl::string_view path,
                             bool allow_extended_connect) {
   QUICHE_VLOG(2) << "Request pseudo-headers: ["
                  << absl::StrJoin(pseudo_headers, ", ")
                  << "], allow_extended_connect: " << allow_extended_connect
+                 << ", authority: "
+                 << (authority ? authority.value() : "<nullopt>")
                  << ", method: " << method << ", path: " << path;
-  if (allow_extended_connect && method == "CONNECT") {
-    static const std::vector<std::string>* kConnectHeaders =
-        new std::vector<std::string>(
-            {":authority", ":method", ":path", ":protocol", ":scheme"});
-    return pseudo_headers == *kConnectHeaders;
+  if (method == "CONNECT") {
+    if (allow_extended_connect) {
+      // See RFC 8441.
+      static const std::vector<std::string>* kExtendedConnectHeaders =
+          new std::vector<std::string>(
+              {":authority", ":method", ":path", ":protocol", ":scheme"});
+      return pseudo_headers == *kExtendedConnectHeaders;
+    } else {
+      // See RFC 7540 Section 8.3.
+      static const std::vector<std::string>* kConnectHeaders =
+          new std::vector<std::string>({":authority", ":method"});
+      return authority.has_value() && !authority.value().empty() &&
+             pseudo_headers == *kConnectHeaders;
+    }
   }
 
   if (path.empty()) {
@@ -220,7 +232,7 @@
   std::sort(pseudo_headers_.begin(), pseudo_headers_.end());
   switch (type) {
     case HeaderType::REQUEST:
-      return ValidateRequestHeaders(pseudo_headers_, method_, path_,
+      return ValidateRequestHeaders(pseudo_headers_, authority_, method_, path_,
                                     allow_extended_connect_);
     case HeaderType::REQUEST_TRAILER:
       return ValidateRequestTrailers(pseudo_headers_);
diff --git a/quiche/http2/adapter/header_validator_test.cc b/quiche/http2/adapter/header_validator_test.cc
index 31ba369..fc3e207 100644
--- a/quiche/http2/adapter/header_validator_test.cc
+++ b/quiche/http2/adapter/header_validator_test.cc
@@ -266,6 +266,45 @@
   }
 }
 
+TEST(HeaderValidatorTest, ConnectHeaders) {
+  // Too few headers.
+  HeaderValidator v;
+  v.StartHeaderBlock();
+  EXPECT_EQ(HeaderValidator::HEADER_OK,
+            v.ValidateSingleHeader(":authority", "athena.dialup.mit.edu:23"));
+  EXPECT_FALSE(v.FinishHeaderBlock(HeaderType::REQUEST));
+
+  v.StartHeaderBlock();
+  EXPECT_EQ(HeaderValidator::HEADER_OK,
+            v.ValidateSingleHeader(":method", "CONNECT"));
+  EXPECT_FALSE(v.FinishHeaderBlock(HeaderType::REQUEST));
+
+  // Too many headers.
+  v.StartHeaderBlock();
+  EXPECT_EQ(HeaderValidator::HEADER_OK,
+            v.ValidateSingleHeader(":authority", "athena.dialup.mit.edu:23"));
+  EXPECT_EQ(HeaderValidator::HEADER_OK,
+            v.ValidateSingleHeader(":method", "CONNECT"));
+  EXPECT_EQ(HeaderValidator::HEADER_OK, v.ValidateSingleHeader(":path", "/"));
+  EXPECT_FALSE(v.FinishHeaderBlock(HeaderType::REQUEST));
+
+  // Empty :authority
+  v.StartHeaderBlock();
+  EXPECT_EQ(HeaderValidator::HEADER_OK,
+            v.ValidateSingleHeader(":authority", ""));
+  EXPECT_EQ(HeaderValidator::HEADER_OK,
+            v.ValidateSingleHeader(":method", "CONNECT"));
+  EXPECT_FALSE(v.FinishHeaderBlock(HeaderType::REQUEST));
+
+  // Just right.
+  v.StartHeaderBlock();
+  EXPECT_EQ(HeaderValidator::HEADER_OK,
+            v.ValidateSingleHeader(":authority", "athena.dialup.mit.edu:23"));
+  EXPECT_EQ(HeaderValidator::HEADER_OK,
+            v.ValidateSingleHeader(":method", "CONNECT"));
+  EXPECT_TRUE(v.FinishHeaderBlock(HeaderType::REQUEST));
+}
+
 TEST(HeaderValidatorTest, WebsocketPseudoHeaders) {
   HeaderValidator v;
   v.StartHeaderBlock();