Skip to content

Commit 8794792

Browse files
authored
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
1 parent b85768c commit 8794792

File tree

2 files changed

+20
-6
lines changed

2 files changed

+20
-6
lines changed

httplib.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5156,7 +5156,18 @@ inline bool range_error(Request &req, Response &res) {
51565156
last_pos = contant_len - 1;
51575157
}
51585158

5159-
if (last_pos == -1) { last_pos = contant_len - 1; }
5159+
// NOTE: RFC-9110 '14.1.2. Byte Ranges':
5160+
// A client can limit the number of bytes requested without knowing the
5161+
// size of the selected representation. If the last-pos value is absent,
5162+
// or if the value is greater than or equal to the current length of the
5163+
// representation data, the byte range is interpreted as the remainder of
5164+
// the representation (i.e., the server replaces the value of last-pos
5165+
// with a value that is one less than the current length of the selected
5166+
// representation).
5167+
// https://www.rfc-editor.org/rfc/rfc9110.html#section-14.1.2-6
5168+
if (last_pos == -1 || last_pos >= contant_len) {
5169+
last_pos = contant_len - 1;
5170+
}
51605171

51615172
// Range must be within content length
51625173
if (!(0 <= first_pos && first_pos <= last_pos &&

test/test.cc

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3795,11 +3795,14 @@ TEST_F(ServerTest, GetRangeWithMaxLongLength) {
37953795
auto res = cli_.Get(
37963796
"/with-range",
37973797
{{"Range",
3798-
"bytes=0-" + std::to_string(std::numeric_limits<long>::max())}});
3799-
EXPECT_EQ(StatusCode::RangeNotSatisfiable_416, res->status);
3800-
EXPECT_EQ("0", res->get_header_value("Content-Length"));
3801-
EXPECT_EQ(false, res->has_header("Content-Range"));
3802-
EXPECT_EQ(0U, res->body.size());
3798+
"bytes=0-" + std::to_string(std::numeric_limits<long>::max())},
3799+
{"Accept-Encoding", ""}});
3800+
ASSERT_TRUE(res);
3801+
EXPECT_EQ(StatusCode::PartialContent_206, res->status);
3802+
EXPECT_EQ("7", res->get_header_value("Content-Length"));
3803+
EXPECT_EQ(true, res->has_header("Content-Range"));
3804+
EXPECT_EQ("bytes 0-6/7", res->get_header_value("Content-Range"));
3805+
EXPECT_EQ(std::string("abcdefg"), res->body);
38033806
}
38043807

38053808
TEST_F(ServerTest, GetRangeWithZeroToInfinite) {

0 commit comments

Comments
 (0)