Added 'Content-Range' header for single range request

This commit is contained in:
yhirose 2019-08-03 22:12:24 +09:00
parent 9785cd47f2
commit c899462e75
2 changed files with 31 additions and 7 deletions

View file

@ -65,10 +65,10 @@ typedef int socket_t;
#include <fcntl.h> #include <fcntl.h>
#include <fstream> #include <fstream>
#include <functional> #include <functional>
#include <list>
#include <map> #include <map>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <list>
#include <random> #include <random>
#include <regex> #include <regex>
#include <string> #include <string>
@ -1690,6 +1690,18 @@ get_range_offset_and_length(const Request &req, uint64_t content_length,
return std::make_pair(r.first, r.second - r.first + 1); return std::make_pair(r.first, r.second - r.first + 1);
} }
inline std::string make_content_range_header_field(uint64_t offset,
uint64_t length,
uint64_t content_length) {
std::string field = "bytes ";
field += std::to_string(offset);
field += "-";
field += std::to_string(offset + length - 1);
field += "/";
field += std::to_string(content_length);
return field;
}
template <typename SToken, typename CToken, typename Content> template <typename SToken, typename CToken, typename Content>
bool process_multipart_ranges_data(const Request &req, Response &res, bool process_multipart_ranges_data(const Request &req, Response &res,
const std::string &boundary, const std::string &boundary,
@ -1710,12 +1722,8 @@ bool process_multipart_ranges_data(const Request &req, Response &res,
auto offset = offsets.first; auto offset = offsets.first;
auto length = offsets.second; auto length = offsets.second;
ctoken("Content-Range: bytes "); ctoken("Content-Range: ");
stoken(std::to_string(offset)); stoken(make_content_range_header_field(offset, length, res.body.size()));
ctoken("-");
stoken(std::to_string(offset + length - 1));
ctoken("/");
stoken(std::to_string(res.body.size()));
ctoken("\r\n"); ctoken("\r\n");
ctoken("\r\n"); ctoken("\r\n");
if (!content(offset, length)) { return false; } if (!content(offset, length)) { return false; }
@ -1824,6 +1832,7 @@ make_basic_authentication_header(const std::string &username,
auto field = "Basic " + detail::base64_encode(username + ":" + password); auto field = "Basic " + detail::base64_encode(username + ":" + password);
return std::make_pair("Authorization", field); return std::make_pair("Authorization", field);
} }
// Request implementation // Request implementation
inline bool Request::has_header(const char *key) const { inline bool Request::has_header(const char *key) const {
return detail::has_header(headers, key); return detail::has_header(headers, key);
@ -2182,7 +2191,11 @@ inline bool Server::write_response(Stream &strm, bool last_connection,
} else if (req.ranges.size() == 1) { } else if (req.ranges.size() == 1) {
auto offsets = auto offsets =
detail::get_range_offset_and_length(req, res.content_length, 0); detail::get_range_offset_and_length(req, res.content_length, 0);
auto offset = offsets.first;
length = offsets.second; length = offsets.second;
auto content_range = detail::make_content_range_header_field(
offset, length, res.content_length);
res.set_header("Content-Range", content_range);
} else { } else {
length = detail::get_multipart_ranges_data_length(req, res, boundary, length = detail::get_multipart_ranges_data_length(req, res, boundary,
content_type); content_type);
@ -2203,6 +2216,9 @@ inline bool Server::write_response(Stream &strm, bool last_connection,
detail::get_range_offset_and_length(req, res.body.size(), 0); detail::get_range_offset_and_length(req, res.body.size(), 0);
auto offset = offsets.first; auto offset = offsets.first;
auto length = offsets.second; auto length = offsets.second;
auto content_range = detail::make_content_range_header_field(
offset, length, res.body.size());
res.set_header("Content-Range", content_range);
res.body = res.body.substr(offset, length); res.body = res.body.substr(offset, length);
} else { } else {
res.body = res.body =

View file

@ -1146,6 +1146,7 @@ TEST_F(ServerTest, GetStreamedWithRange1) {
ASSERT_TRUE(res != nullptr); ASSERT_TRUE(res != nullptr);
EXPECT_EQ(206, res->status); EXPECT_EQ(206, res->status);
EXPECT_EQ("3", res->get_header_value("Content-Length")); EXPECT_EQ("3", res->get_header_value("Content-Length"));
EXPECT_EQ(true, res->has_header("Content-Range"));
EXPECT_EQ(std::string("def"), res->body); EXPECT_EQ(std::string("def"), res->body);
} }
@ -1154,6 +1155,7 @@ TEST_F(ServerTest, GetStreamedWithRange2) {
ASSERT_TRUE(res != nullptr); ASSERT_TRUE(res != nullptr);
EXPECT_EQ(206, res->status); EXPECT_EQ(206, res->status);
EXPECT_EQ("6", res->get_header_value("Content-Length")); EXPECT_EQ("6", res->get_header_value("Content-Length"));
EXPECT_EQ(true, res->has_header("Content-Range"));
EXPECT_EQ(std::string("bcdefg"), res->body); EXPECT_EQ(std::string("bcdefg"), res->body);
} }
@ -1163,6 +1165,7 @@ TEST_F(ServerTest, GetStreamedWithRangeMultipart) {
ASSERT_TRUE(res != nullptr); ASSERT_TRUE(res != nullptr);
EXPECT_EQ(206, res->status); EXPECT_EQ(206, res->status);
EXPECT_EQ("269", res->get_header_value("Content-Length")); EXPECT_EQ("269", res->get_header_value("Content-Length"));
EXPECT_EQ(false, res->has_header("Content-Range"));
EXPECT_EQ(269, res->body.size()); EXPECT_EQ(269, res->body.size());
} }
@ -1171,6 +1174,7 @@ TEST_F(ServerTest, GetWithRange1) {
ASSERT_TRUE(res != nullptr); ASSERT_TRUE(res != nullptr);
EXPECT_EQ(206, res->status); EXPECT_EQ(206, res->status);
EXPECT_EQ("3", res->get_header_value("Content-Length")); EXPECT_EQ("3", res->get_header_value("Content-Length"));
EXPECT_EQ(true, res->has_header("Content-Range"));
EXPECT_EQ(std::string("def"), res->body); EXPECT_EQ(std::string("def"), res->body);
} }
@ -1179,6 +1183,7 @@ TEST_F(ServerTest, GetWithRange2) {
ASSERT_TRUE(res != nullptr); ASSERT_TRUE(res != nullptr);
EXPECT_EQ(206, res->status); EXPECT_EQ(206, res->status);
EXPECT_EQ("6", res->get_header_value("Content-Length")); EXPECT_EQ("6", res->get_header_value("Content-Length"));
EXPECT_EQ(true, res->has_header("Content-Range"));
EXPECT_EQ(std::string("bcdefg"), res->body); EXPECT_EQ(std::string("bcdefg"), res->body);
} }
@ -1187,6 +1192,7 @@ TEST_F(ServerTest, GetWithRange3) {
ASSERT_TRUE(res != nullptr); ASSERT_TRUE(res != nullptr);
EXPECT_EQ(206, res->status); EXPECT_EQ(206, res->status);
EXPECT_EQ("1", res->get_header_value("Content-Length")); EXPECT_EQ("1", res->get_header_value("Content-Length"));
EXPECT_EQ(true, res->has_header("Content-Range"));
EXPECT_EQ(std::string("a"), res->body); EXPECT_EQ(std::string("a"), res->body);
} }
@ -1195,6 +1201,7 @@ TEST_F(ServerTest, GetWithRange4) {
ASSERT_TRUE(res != nullptr); ASSERT_TRUE(res != nullptr);
EXPECT_EQ(206, res->status); EXPECT_EQ(206, res->status);
EXPECT_EQ("2", res->get_header_value("Content-Length")); EXPECT_EQ("2", res->get_header_value("Content-Length"));
EXPECT_EQ(true, res->has_header("Content-Range"));
EXPECT_EQ(std::string("fg"), res->body); EXPECT_EQ(std::string("fg"), res->body);
} }
@ -1203,6 +1210,7 @@ TEST_F(ServerTest, GetWithRangeMultipart) {
ASSERT_TRUE(res != nullptr); ASSERT_TRUE(res != nullptr);
EXPECT_EQ(206, res->status); EXPECT_EQ(206, res->status);
EXPECT_EQ("269", res->get_header_value("Content-Length")); EXPECT_EQ("269", res->get_header_value("Content-Length"));
EXPECT_EQ(false, res->has_header("Content-Range"));
EXPECT_EQ(269, res->body.size()); EXPECT_EQ(269, res->body.size());
} }