فهرست منبع

Fix #2279

Enhance request handling: add support for requests without Content-Length or Transfer-Encoding headers
yhirose 4 ماه پیش
والد
کامیت
337fbb0793
2فایلهای تغییر یافته به همراه78 افزوده شده و 4 حذف شده
  1. 5 1
      httplib.h
  2. 73 3
      test/test.cc

+ 5 - 1
httplib.h

@@ -7932,7 +7932,11 @@ inline bool Server::read_content_core(
                      size_t /*len*/) { return receiver(buf, n); };
   }
 
-  if (req.method == "DELETE" && !req.has_header("Content-Length")) {
+  // RFC 7230 Section 3.3.3: If this is a request message and none of the above
+  // are true (no Transfer-Encoding and no Content-Length), then the message
+  // body length is zero (no message body is present).
+  if (!req.has_header("Content-Length") &&
+      !detail::is_chunked_transfer_encoding(req.headers)) {
     return true;
   }
 

+ 73 - 3
test/test.cc

@@ -3424,7 +3424,7 @@ protected:
                 res.set_content(req.body, "text/plain");
               })
         .Post("/post-loopback",
-              [&](const Request &req, Response &res,
+              [&](const Request &, Response &res,
                   ContentReader const &content_reader) {
                 std::string body;
                 content_reader([&](const char *data, size_t data_length) {
@@ -3435,7 +3435,7 @@ protected:
                 res.set_content(body, "text/plain");
               })
         .Put("/put-loopback",
-             [&](const Request &req, Response &res,
+             [&](const Request &, Response &res,
                  ContentReader const &content_reader) {
                std::string body;
                content_reader([&](const char *data, size_t data_length) {
@@ -3446,7 +3446,7 @@ protected:
                res.set_content(body, "text/plain");
              })
         .Patch("/patch-loopback",
-               [&](const Request &req, Response &res,
+               [&](const Request &, Response &res,
                    ContentReader const &content_reader) {
                  std::string body;
                  content_reader([&](const char *data, size_t data_length) {
@@ -11609,3 +11609,73 @@ TEST(ForwardedHeadersTest, HandlesWhitespaceAroundIPs) {
   EXPECT_EQ(observed_xff, "198.51.100.23 , 203.0.113.66 , 192.0.2.45");
   EXPECT_EQ(observed_remote_addr, "203.0.113.66");
 }
+
+TEST(ServerRequestParsingTest, RequestWithoutContentLengthOrTransferEncoding) {
+  Server svr;
+
+  svr.Post("/post", [&](const Request &req, Response &res) {
+    res.set_content(req.body, "text/plain");
+  });
+
+  svr.Put("/put", [&](const Request &req, Response &res) {
+    res.set_content(req.body, "text/plain");
+  });
+
+  svr.Patch("/patch", [&](const Request &req, Response &res) {
+    res.set_content(req.body, "text/plain");
+  });
+
+  svr.Delete("/delete", [&](const Request &req, Response &res) {
+    res.set_content(req.body, "text/plain");
+  });
+
+  thread t = thread([&]() { svr.listen(HOST, PORT); });
+  auto se = detail::scope_exit([&] {
+    svr.stop();
+    t.join();
+    ASSERT_FALSE(svr.is_running());
+  });
+
+  svr.wait_until_ready();
+
+  std::string resp;
+
+  // POST without Content-Length
+  ASSERT_TRUE(send_request(5,
+                           "POST /post HTTP/1.1\r\n"
+                           "Host: localhost\r\n"
+                           "Connection: close\r\n"
+                           "\r\n",
+                           &resp));
+  EXPECT_TRUE(resp.find("HTTP/1.1 200 OK") == 0);
+
+  // PUT without Content-Length
+  resp.clear();
+  ASSERT_TRUE(send_request(5,
+                           "PUT /put HTTP/1.1\r\n"
+                           "Host: localhost\r\n"
+                           "Connection: close\r\n"
+                           "\r\n",
+                           &resp));
+  EXPECT_TRUE(resp.find("HTTP/1.1 200 OK") == 0);
+
+  // PATCH without Content-Length
+  resp.clear();
+  ASSERT_TRUE(send_request(5,
+                           "PATCH /patch HTTP/1.1\r\n"
+                           "Host: localhost\r\n"
+                           "Connection: close\r\n"
+                           "\r\n",
+                           &resp));
+  EXPECT_TRUE(resp.find("HTTP/1.1 200 OK") == 0);
+
+  // DELETE without Content-Length
+  resp.clear();
+  ASSERT_TRUE(send_request(5,
+                           "DELETE /delete HTTP/1.1\r\n"
+                           "Host: localhost\r\n"
+                           "Connection: close\r\n"
+                           "\r\n",
+                           &resp));
+  EXPECT_TRUE(resp.find("HTTP/1.1 200 OK") == 0);
+}