mirror of
https://github.com/yhirose/cpp-httplib
synced 2024-11-21 14:29:10 -07:00
Added 'Content-Range' header for single range request
This commit is contained in:
parent
9785cd47f2
commit
c899462e75
2 changed files with 31 additions and 7 deletions
30
httplib.h
30
httplib.h
|
@ -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 =
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue