Browse Source

Ignore ranges for unknown-length streams (#2465)

Florian Fischer 2 months ago
parent
commit
c7ba963a17
2 changed files with 35 additions and 0 deletions
  1. 8 0
      httplib.h
  2. 27 0
      test/test.cc

+ 8 - 0
httplib.h

@@ -8443,6 +8443,14 @@ inline void coalesce_ranges(Ranges &ranges, size_t content_length) {
 
 inline bool range_error(Request &req, Response &res) {
   if (!req.ranges.empty() && 200 <= res.status && res.status < 300) {
+    if (res.body.empty() && res.content_provider_ && res.content_length_ == 0) {
+      req.ranges.clear();
+      if (res.status == StatusCode::PartialContent_206) {
+        res.status = StatusCode::OK_200;
+      }
+      return false;
+    }
+
     ssize_t content_len = static_cast<ssize_t>(
         res.content_length_ ? res.content_length_ : res.body.size());
 

+ 27 - 0
test/test.cc

@@ -3718,6 +3718,23 @@ protected:
                      return true;
                    });
              })
+        .Get("/streamed-without-length",
+             [&](const Request & /*req*/, Response &res) {
+               auto data = new std::string("abcdefg");
+               res.set_content_provider(
+                   "text/plain",
+                   [data](size_t offset, DataSink &sink) {
+                     if (offset < data->size()) {
+                       sink.os << data->substr(offset);
+                     }
+                     sink.done();
+                     return true;
+                   },
+                   [data](bool success) {
+                     EXPECT_TRUE(success);
+                     delete data;
+                   });
+             })
         .Get("/streamed-with-range",
              [&](const Request &req, Response &res) {
                auto data = new std::string("abcdefg");
@@ -5197,6 +5214,16 @@ TEST_F(ServerTest, GetStreamed) {
   EXPECT_EQ(std::string("aaabbb"), res->body);
 }
 
+TEST_F(ServerTest, GetStreamedWithoutLengthWithRange) {
+  auto res =
+      cli_.Get("/streamed-without-length", {make_range_header({{0, -1}})});
+  ASSERT_TRUE(res);
+  EXPECT_EQ(StatusCode::OK_200, res->status);
+  EXPECT_EQ(false, res->has_header("Content-Length"));
+  EXPECT_EQ(false, res->has_header("Content-Range"));
+  EXPECT_EQ(std::string("abcdefg"), res->body);
+}
+
 TEST_F(ServerTest, GetStreamedWithRange1) {
   auto res = cli_.Get("/streamed-with-range", {{make_range_header({{3, 5}})}});
   ASSERT_TRUE(res);