diff --git a/httplib.h b/httplib.h index 3297c51..ec9809c 100644 --- a/httplib.h +++ b/httplib.h @@ -8,7 +8,7 @@ #ifndef CPPHTTPLIB_HTTPLIB_H #define CPPHTTPLIB_HTTPLIB_H -#define CPPHTTPLIB_VERSION "0.15.0" +#define CPPHTTPLIB_VERSION "0.14.3" /* * Configuration @@ -141,11 +141,11 @@ using ssize_t = long; #endif // _MSC_VER #ifndef S_ISREG -#define S_ISREG(m) (((m)&S_IFREG) == S_IFREG) +#define S_ISREG(m) (((m) & S_IFREG) == S_IFREG) #endif // S_ISREG #ifndef S_ISDIR -#define S_ISDIR(m) (((m)&S_IFDIR) == S_IFDIR) +#define S_ISDIR(m) (((m) & S_IFDIR) == S_IFDIR) #endif // S_ISDIR #ifndef NOMINMAX @@ -4647,7 +4647,8 @@ inline std::string random_string(size_t length) { static std::random_device seed_gen; // Request 128 bits of entropy for initialization - static std::seed_seq seed_sequence{seed_gen(), seed_gen(), seed_gen(), seed_gen()}; + static std::seed_seq seed_sequence{seed_gen(), seed_gen(), seed_gen(), + seed_gen()}; static std::mt19937 engine(seed_sequence); @@ -4720,32 +4721,41 @@ serialize_multipart_formdata(const MultipartFormDataItems &items, } inline std::pair -get_range_offset_and_length(const Request &req, size_t content_length, - size_t index) { - auto r = req.ranges[index]; - - if (r.first == -1 && r.second == -1) { +get_range_offset_and_length(Range range, size_t content_length) { + if (range.first == -1 && range.second == -1) { return std::make_pair(0, content_length); } auto slen = static_cast(content_length); - if (r.first == -1) { - r.first = (std::max)(static_cast(0), slen - r.second); - r.second = slen - 1; + if (range.first == -1) { + range.first = (std::max)(static_cast(0), slen - range.second); + range.second = slen - 1; } - if (r.second == -1) { r.second = slen - 1; } - return std::make_pair(r.first, static_cast(r.second - r.first) + 1); + if (range.second == -1) { range.second = slen - 1; } + return std::make_pair(range.first, + static_cast(range.second - range.first) + 1); +} + +inline std::pair +get_range_offset_and_length(const Request &req, size_t content_length, + size_t index) { + return get_range_offset_and_length(req.ranges[index], content_length); } inline std::string make_content_range_header_field(const std::pair &range, size_t content_length) { + + auto ret = get_range_offset_and_length(range, content_length); + auto st = ret.first; + auto ed = (std::min)(st + ret.second - 1, content_length - 1); + std::string field = "bytes "; - if (range.first != -1) { field += std::to_string(range.first); } + field += std::to_string(st); field += "-"; - if (range.second != -1) { field += std::to_string(range.second); } + field += std::to_string(ed); field += "/"; field += std::to_string(content_length); return field; @@ -4773,9 +4783,9 @@ bool process_multipart_ranges_data(const Request &req, Response &res, ctoken("\r\n"); ctoken("\r\n"); - auto offsets = get_range_offset_and_length(req, res.content_length_, i); - auto offset = offsets.first; - auto length = offsets.second; + auto ret = get_range_offset_and_length(req, res.content_length_, i); + auto offset = ret.first; + auto length = ret.second; if (!content(offset, length)) { return false; } ctoken("\r\n"); } @@ -4838,18 +4848,6 @@ inline bool write_multipart_ranges_data(Stream &strm, const Request &req, }); } -inline std::pair -get_range_offset_and_length(const Request &req, const Response &res, - size_t index) { - auto r = req.ranges[index]; - - if (r.second == -1) { - r.second = static_cast(res.content_length_) - 1; - } - - return std::make_pair(r.first, r.second - r.first + 1); -} - inline bool expect_content(const Request &req) { if (req.method == "POST" || req.method == "PUT" || req.method == "PATCH" || req.method == "PRI" || req.method == "DELETE") { @@ -6045,10 +6043,10 @@ Server::write_content_with_provider(Stream &strm, const Request &req, return detail::write_content(strm, res.content_provider_, 0, res.content_length_, is_shutting_down); } else if (req.ranges.size() == 1) { - auto offsets = + auto ret = detail::get_range_offset_and_length(req, res.content_length_, 0); - auto offset = offsets.first; - auto length = offsets.second; + auto offset = ret.first; + auto length = ret.second; return detail::write_content(strm, res.content_provider_, offset, length, is_shutting_down); } else { @@ -6465,9 +6463,9 @@ inline void Server::apply_ranges(const Request &req, Response &res, if (req.ranges.empty()) { length = res.content_length_; } else if (req.ranges.size() == 1) { - auto offsets = + auto ret = detail::get_range_offset_and_length(req, res.content_length_, 0); - length = offsets.second; + length = ret.second; auto content_range = detail::make_content_range_header_field( req.ranges[0], res.content_length_); @@ -6497,10 +6495,9 @@ inline void Server::apply_ranges(const Request &req, Response &res, req.ranges[0], res.body.size()); res.set_header("Content-Range", content_range); - auto offsets = - detail::get_range_offset_and_length(req, res.body.size(), 0); - auto offset = offsets.first; - auto length = offsets.second; + auto ret = detail::get_range_offset_and_length(req, res.body.size(), 0); + auto offset = ret.first; + auto length = ret.second; if (offset < res.body.size()) { res.body = res.body.substr(offset, length); diff --git a/test/test.cc b/test/test.cc index 1d236ee..e33ab41 100644 --- a/test/test.cc +++ b/test/test.cc @@ -2540,6 +2540,7 @@ TEST_F(ServerTest, StaticFileRange) { EXPECT_EQ("text/abcde", res->get_header_value("Content-Type")); EXPECT_EQ("2", res->get_header_value("Content-Length")); EXPECT_EQ(true, res->has_header("Content-Range")); + EXPECT_EQ("bytes 2-3/5", res->get_header_value("Content-Range")); EXPECT_EQ(std::string("cd"), res->body); } @@ -2553,7 +2554,7 @@ TEST_F(ServerTest, StaticFileRanges) { .find( "multipart/byteranges; boundary=--cpp-httplib-multipart-data-") == 0); - EXPECT_EQ("265", res->get_header_value("Content-Length")); + EXPECT_EQ("266", res->get_header_value("Content-Length")); } TEST_F(ServerTest, StaticFileRangeHead) { @@ -2563,6 +2564,7 @@ TEST_F(ServerTest, StaticFileRangeHead) { EXPECT_EQ("text/abcde", res->get_header_value("Content-Type")); EXPECT_EQ("2", res->get_header_value("Content-Length")); EXPECT_EQ(true, res->has_header("Content-Range")); + EXPECT_EQ("bytes 2-3/5", res->get_header_value("Content-Range")); } TEST_F(ServerTest, StaticFileRangeBigFile) { @@ -2572,6 +2574,8 @@ TEST_F(ServerTest, StaticFileRangeBigFile) { EXPECT_EQ("text/plain", res->get_header_value("Content-Type")); EXPECT_EQ("5", res->get_header_value("Content-Length")); EXPECT_EQ(true, res->has_header("Content-Range")); + EXPECT_EQ("bytes 1048571-1048575/1048576", + res->get_header_value("Content-Range")); EXPECT_EQ("LAST\n", res->body); } @@ -2582,6 +2586,7 @@ TEST_F(ServerTest, StaticFileRangeBigFile2) { EXPECT_EQ("text/plain", res->get_header_value("Content-Type")); EXPECT_EQ("4097", res->get_header_value("Content-Length")); EXPECT_EQ(true, res->has_header("Content-Range")); + EXPECT_EQ("bytes 1-4097/1048576", res->get_header_value("Content-Range")); } TEST_F(ServerTest, StaticFileBigFile) { @@ -2908,6 +2913,8 @@ TEST_F(ServerTest, GetStreamed2) { ASSERT_TRUE(res); EXPECT_EQ(StatusCode::PartialContent_206, res->status); EXPECT_EQ("2", res->get_header_value("Content-Length")); + EXPECT_EQ(true, res->has_header("Content-Range")); + EXPECT_EQ("bytes 2-3/6", res->get_header_value("Content-Range")); EXPECT_EQ(std::string("ab"), res->body); } @@ -2925,6 +2932,7 @@ TEST_F(ServerTest, GetStreamedWithRange1) { EXPECT_EQ(StatusCode::PartialContent_206, res->status); EXPECT_EQ("3", res->get_header_value("Content-Length")); EXPECT_EQ(true, res->has_header("Content-Range")); + EXPECT_EQ("bytes 3-5/7", res->get_header_value("Content-Range")); EXPECT_EQ(std::string("def"), res->body); } @@ -2934,6 +2942,7 @@ TEST_F(ServerTest, GetStreamedWithRange2) { EXPECT_EQ(StatusCode::PartialContent_206, res->status); EXPECT_EQ("6", res->get_header_value("Content-Length")); EXPECT_EQ(true, res->has_header("Content-Range")); + EXPECT_EQ("bytes 1-6/7", res->get_header_value("Content-Range")); EXPECT_EQ(std::string("bcdefg"), res->body); } @@ -2943,6 +2952,7 @@ TEST_F(ServerTest, GetStreamedWithRangeSuffix1) { EXPECT_EQ(StatusCode::PartialContent_206, res->status); EXPECT_EQ("3", res->get_header_value("Content-Length")); EXPECT_EQ(true, res->has_header("Content-Range")); + EXPECT_EQ("bytes 4-6/7", res->get_header_value("Content-Range")); EXPECT_EQ(std::string("efg"), res->body); } @@ -2952,6 +2962,7 @@ TEST_F(ServerTest, GetStreamedWithRangeSuffix2) { 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); } @@ -2968,6 +2979,7 @@ TEST_F(ServerTest, GetRangeWithMaxLongLength) { cli_.Get("/with-range", {{"Range", "bytes=0-9223372036854775807"}}); EXPECT_EQ(StatusCode::PartialContent_206, res->status); EXPECT_EQ("7", res->get_header_value("Content-Length")); + EXPECT_EQ("bytes 0-6/7", res->get_header_value("Content-Range")); EXPECT_EQ(true, res->has_header("Content-Range")); EXPECT_EQ(std::string("abcdefg"), res->body); } @@ -3029,6 +3041,7 @@ TEST_F(ServerTest, GetWithRange1) { EXPECT_EQ(StatusCode::PartialContent_206, res->status); EXPECT_EQ("3", res->get_header_value("Content-Length")); EXPECT_EQ(true, res->has_header("Content-Range")); + EXPECT_EQ("bytes 3-5/7", res->get_header_value("Content-Range")); EXPECT_EQ(std::string("def"), res->body); } @@ -3038,6 +3051,7 @@ TEST_F(ServerTest, GetWithRange2) { EXPECT_EQ(StatusCode::PartialContent_206, res->status); EXPECT_EQ("6", res->get_header_value("Content-Length")); EXPECT_EQ(true, res->has_header("Content-Range")); + EXPECT_EQ("bytes 1-6/7", res->get_header_value("Content-Range")); EXPECT_EQ(std::string("bcdefg"), res->body); } @@ -3047,6 +3061,7 @@ TEST_F(ServerTest, GetWithRange3) { EXPECT_EQ(StatusCode::PartialContent_206, res->status); EXPECT_EQ("1", res->get_header_value("Content-Length")); EXPECT_EQ(true, res->has_header("Content-Range")); + EXPECT_EQ("bytes 0-0/7", res->get_header_value("Content-Range")); EXPECT_EQ(std::string("a"), res->body); } @@ -3056,6 +3071,7 @@ TEST_F(ServerTest, GetWithRange4) { EXPECT_EQ(StatusCode::PartialContent_206, res->status); EXPECT_EQ("2", res->get_header_value("Content-Length")); EXPECT_EQ(true, res->has_header("Content-Range")); + EXPECT_EQ("bytes 5-6/7", res->get_header_value("Content-Range")); EXPECT_EQ(std::string("fg"), res->body); }