Browse Source

Treat out-of-range last_pos as the end of the content (#2009)

RFC-9110 '14.1.2. Byte Ranges':
A client can limit the number of bytes requested without knowing the
size of the selected representation. If the last-pos value is absent,
or if the value is greater than or equal to the current length of the
representation data, the byte range is interpreted as the remainder of
the representation (i.e., the server replaces the value of last-pos
with a value that is one less than the current length of the selected
representation).

https://www.rfc-editor.org/rfc/rfc9110.html#section-14.1.2-6
Sergey Bobrenok 1 năm trước cách đây
mục cha
commit
8794792baa
2 tập tin đã thay đổi với 20 bổ sung6 xóa
  1. 12 1
      httplib.h
  2. 8 5
      test/test.cc

+ 12 - 1
httplib.h

@@ -5156,7 +5156,18 @@ inline bool range_error(Request &req, Response &res) {
         last_pos = contant_len - 1;
       }
 
-      if (last_pos == -1) { last_pos = contant_len - 1; }
+      // NOTE: RFC-9110 '14.1.2. Byte Ranges':
+      // A client can limit the number of bytes requested without knowing the
+      // size of the selected representation. If the last-pos value is absent,
+      // or if the value is greater than or equal to the current length of the
+      // representation data, the byte range is interpreted as the remainder of
+      // the representation (i.e., the server replaces the value of last-pos
+      // with a value that is one less than the current length of the selected
+      // representation).
+      // https://www.rfc-editor.org/rfc/rfc9110.html#section-14.1.2-6
+      if (last_pos == -1 || last_pos >= contant_len) {
+          last_pos = contant_len - 1;
+      }
 
       // Range must be within content length
       if (!(0 <= first_pos && first_pos <= last_pos &&

+ 8 - 5
test/test.cc

@@ -3795,11 +3795,14 @@ TEST_F(ServerTest, GetRangeWithMaxLongLength) {
   auto res = cli_.Get(
       "/with-range",
       {{"Range",
-        "bytes=0-" + std::to_string(std::numeric_limits<long>::max())}});
-  EXPECT_EQ(StatusCode::RangeNotSatisfiable_416, res->status);
-  EXPECT_EQ("0", res->get_header_value("Content-Length"));
-  EXPECT_EQ(false, res->has_header("Content-Range"));
-  EXPECT_EQ(0U, res->body.size());
+        "bytes=0-" + std::to_string(std::numeric_limits<long>::max())},
+       {"Accept-Encoding", ""}});
+  ASSERT_TRUE(res);
+  EXPECT_EQ(StatusCode::PartialContent_206, res->status);
+  EXPECT_EQ("7", res->get_header_value("Content-Length"));
+  EXPECT_EQ(true, res->has_header("Content-Range"));
+  EXPECT_EQ("bytes 0-6/7", res->get_header_value("Content-Range"));
+  EXPECT_EQ(std::string("abcdefg"), res->body);
 }
 
 TEST_F(ServerTest, GetRangeWithZeroToInfinite) {