Add HttpValidationPolicy::require_content_length_if_body_required.

When set to false, this instructs BalsaFrame to ignore
REQUIRED_BODY_BUT_NO_CONTENT_LENGTH errors.

PiperOrigin-RevId: 540011529
diff --git a/quiche/balsa/balsa_frame.cc b/quiche/balsa/balsa_frame.cc
index f066c18..cd388846 100644
--- a/quiche/balsa/balsa_frame.cc
+++ b/quiche/balsa/balsa_frame.cc
@@ -719,7 +719,8 @@
         const absl::string_view method = headers_->request_method();
         // POSTs and PUTs should have a detectable body length.  If they
         // do not we consider it an error.
-        if (method != "POST" && method != "PUT") {
+        if ((method != "POST" && method != "PUT") ||
+            !http_validation_policy().require_content_length_if_body_required) {
           parse_state_ = BalsaFrameEnums::MESSAGE_FULLY_READ;
           break;
         } else if (!allow_reading_until_close_for_request_) {
diff --git a/quiche/balsa/balsa_frame_test.cc b/quiche/balsa/balsa_frame_test.cc
index 83dc611..9b1db61 100644
--- a/quiche/balsa/balsa_frame_test.cc
+++ b/quiche/balsa/balsa_frame_test.cc
@@ -1070,6 +1070,20 @@
   EXPECT_EQ(error_code, balsa_frame_.ErrorCode());
 }
 
+TEST_F(HTTPBalsaFrameTest, ContentLengthNotRequired) {
+  HttpValidationPolicy http_validation_policy;
+  http_validation_policy.require_content_length_if_body_required = false;
+  balsa_frame_.set_http_validation_policy(http_validation_policy);
+
+  std::string message =
+      "PUT /search?q=fo HTTP/1.1\n"
+      "\n";
+
+  balsa_frame_.ProcessInput(message.data(), message.size());
+  EXPECT_TRUE(balsa_frame_.MessageFullyRead());
+  EXPECT_FALSE(balsa_frame_.Error());
+}
+
 TEST_F(HTTPBalsaFrameTest,
        VisitorInvokedProperlyForPermittedMissingContentLength) {
   std::string message =
diff --git a/quiche/balsa/http_validation_policy.h b/quiche/balsa/http_validation_policy.h
index 67ad534..a67093b 100644
--- a/quiche/balsa/http_validation_policy.h
+++ b/quiche/balsa/http_validation_policy.h
@@ -37,6 +37,11 @@
   // still make an effort to determine whether chunked transfer encoding is
   // indicated.
   bool validate_transfer_encoding = true;
+
+  // If true, signal a REQUIRED_BODY_BUT_NO_CONTENT_LENGTH error if a request
+  // with a method POST or PUT, which requires a body, has neither a
+  // "Content-Length" nor a "Transfer-Encoding: chunked" header.
+  bool require_content_length_if_body_required = true;
 };
 
 }  // namespace quiche