This commit is contained in:
yhirose 2020-10-19 21:41:51 -04:00
parent e155ba44bb
commit 4bb001351c
2 changed files with 79 additions and 72 deletions

View File

@ -803,8 +803,7 @@ public:
Result Post(const char *path, const Headers &headers, Result Post(const char *path, const Headers &headers,
const MultipartFormDataItems &items); const MultipartFormDataItems &items);
Result Post(const char *path, const Headers &headers, Result Post(const char *path, const Headers &headers,
const MultipartFormDataItems &items, const MultipartFormDataItems &items, const std::string &boundary);
const std::string& boundary);
Result Put(const char *path); Result Put(const char *path);
Result Put(const char *path, const std::string &body, Result Put(const char *path, const std::string &body,
@ -1041,8 +1040,7 @@ public:
Result Post(const char *path, const Headers &headers, Result Post(const char *path, const Headers &headers,
const MultipartFormDataItems &items); const MultipartFormDataItems &items);
Result Post(const char *path, const Headers &headers, Result Post(const char *path, const Headers &headers,
const MultipartFormDataItems &items, const MultipartFormDataItems &items, const std::string &boundary);
const std::string& boundary);
Result Put(const char *path); Result Put(const char *path);
Result Put(const char *path, const std::string &body, Result Put(const char *path, const std::string &body,
const char *content_type); const char *content_type);
@ -2650,7 +2648,8 @@ bool read_content(Stream &strm, T &x, size_t payload_max_length, int &status,
Progress progress, ContentReceiver receiver, Progress progress, ContentReceiver receiver,
bool decompress) { bool decompress) {
return prepare_content_receiver( return prepare_content_receiver(
x, status, std::move(receiver), decompress, [&](const ContentReceiver &out) { x, status, std::move(receiver), decompress,
[&](const ContentReceiver &out) {
auto ret = true; auto ret = true;
auto exceed_payload_max_length = false; auto exceed_payload_max_length = false;
@ -2907,7 +2906,9 @@ inline bool parse_multipart_boundary(const std::string &content_type,
} }
inline bool parse_range_header(const std::string &s, Ranges &ranges) { inline bool parse_range_header(const std::string &s, Ranges &ranges) {
static auto re_first_range = std::regex(R"(bytes=(\d*-\d*(?:,\s*\d*-\d*)*))"); try {
static auto re_first_range =
std::regex(R"(bytes=(\d*-\d*(?:,\s*\d*-\d*)*))");
std::smatch m; std::smatch m;
if (std::regex_match(s, m, re_first_range)) { if (std::regex_match(s, m, re_first_range)) {
auto pos = static_cast<size_t>(m.position(1)); auto pos = static_cast<size_t>(m.position(1));
@ -2938,6 +2939,7 @@ inline bool parse_range_header(const std::string &s, Ranges &ranges) {
return all_valid_ranges; return all_valid_ranges;
} }
return false; return false;
} catch (...) { return false; }
} }
class MultipartFormDataParser { class MultipartFormDataParser {
@ -2949,7 +2951,8 @@ public:
bool is_valid() const { return is_valid_; } bool is_valid() const { return is_valid_; }
template <typename T, typename U> template <typename T, typename U>
bool parse(const char *buf, size_t n, const T &content_callback, const U &header_callback) { bool parse(const char *buf, size_t n, const T &content_callback,
const U &header_callback) {
static const std::regex re_content_disposition( static const std::regex re_content_disposition(
"^Content-Disposition:\\s*form-data;\\s*name=\"(.*?)\"(?:;\\s*filename=" "^Content-Disposition:\\s*form-data;\\s*name=\"(.*?)\"(?:;\\s*filename="
@ -3797,14 +3800,14 @@ inline Server::Server()
inline Server::~Server() {} inline Server::~Server() {}
inline Server &Server::Get(const char *pattern, Handler handler) { inline Server &Server::Get(const char *pattern, Handler handler) {
get_handlers_.push_back(std::make_pair(std::regex(pattern), get_handlers_.push_back(
std::move(handler))); std::make_pair(std::regex(pattern), std::move(handler)));
return *this; return *this;
} }
inline Server &Server::Post(const char *pattern, Handler handler) { inline Server &Server::Post(const char *pattern, Handler handler) {
post_handlers_.push_back(std::make_pair(std::regex(pattern), post_handlers_.push_back(
std::move(handler))); std::make_pair(std::regex(pattern), std::move(handler)));
return *this; return *this;
} }
@ -3816,8 +3819,8 @@ inline Server &Server::Post(const char *pattern,
} }
inline Server &Server::Put(const char *pattern, Handler handler) { inline Server &Server::Put(const char *pattern, Handler handler) {
put_handlers_.push_back(std::make_pair(std::regex(pattern), put_handlers_.push_back(
std::move(handler))); std::make_pair(std::regex(pattern), std::move(handler)));
return *this; return *this;
} }
@ -3829,8 +3832,8 @@ inline Server &Server::Put(const char *pattern,
} }
inline Server &Server::Patch(const char *pattern, Handler handler) { inline Server &Server::Patch(const char *pattern, Handler handler) {
patch_handlers_.push_back(std::make_pair(std::regex(pattern), patch_handlers_.push_back(
std::move(handler))); std::make_pair(std::regex(pattern), std::move(handler)));
return *this; return *this;
} }
@ -3842,8 +3845,8 @@ inline Server &Server::Patch(const char *pattern,
} }
inline Server &Server::Delete(const char *pattern, Handler handler) { inline Server &Server::Delete(const char *pattern, Handler handler) {
delete_handlers_.push_back(std::make_pair(std::regex(pattern), delete_handlers_.push_back(
std::move(handler))); std::make_pair(std::regex(pattern), std::move(handler)));
return *this; return *this;
} }
@ -3855,8 +3858,8 @@ inline Server &Server::Delete(const char *pattern,
} }
inline Server &Server::Options(const char *pattern, Handler handler) { inline Server &Server::Options(const char *pattern, Handler handler) {
options_handlers_.push_back(std::make_pair(std::regex(pattern), options_handlers_.push_back(
std::move(handler))); std::make_pair(std::regex(pattern), std::move(handler)));
return *this; return *this;
} }
@ -4314,7 +4317,7 @@ inline bool Server::handle_file_request(Request &req, Response &res,
auto type = auto type =
detail::find_content_type(path, file_extension_and_mimetype_map_); detail::find_content_type(path, file_extension_and_mimetype_map_);
if (type) { res.set_header("Content-Type", type); } if (type) { res.set_header("Content-Type", type); }
for (const auto& kv : entry.headers) { for (const auto &kv : entry.headers) {
res.set_header(kv.first.c_str(), kv.second); res.set_header(kv.first.c_str(), kv.second);
} }
res.status = 200; res.status = 200;
@ -4435,9 +4438,8 @@ inline bool Server::routing(Request &req, Response &res, Stream &strm) {
{ {
ContentReader reader( ContentReader reader(
[&](ContentReceiver receiver) { [&](ContentReceiver receiver) {
return read_content_with_content_receiver(strm, req, res, return read_content_with_content_receiver(
std::move(receiver), strm, req, res, std::move(receiver), nullptr, nullptr);
nullptr, nullptr);
}, },
[&](MultipartContentHeader header, ContentReceiver receiver) { [&](MultipartContentHeader header, ContentReceiver receiver) {
return read_content_with_content_receiver(strm, req, res, nullptr, return read_content_with_content_receiver(strm, req, res, nullptr,
@ -4580,7 +4582,8 @@ Server::process_request(Stream &strm, bool close_connection,
if (req.has_header("Range")) { if (req.has_header("Range")) {
const auto &range_header_value = req.get_header_value("Range"); const auto &range_header_value = req.get_header_value("Range");
if (!detail::parse_range_header(range_header_value, req.ranges)) { if (!detail::parse_range_header(range_header_value, req.ranges)) {
// TODO: error res.status = 416;
return write_response(strm, close_connection, req, res);
} }
} }
@ -5160,10 +5163,9 @@ inline bool ClientImpl::process_request(Stream &strm, const Request &req,
inline bool inline bool
ClientImpl::process_socket(Socket &socket, ClientImpl::process_socket(Socket &socket,
std::function<bool(Stream &strm)> callback) { std::function<bool(Stream &strm)> callback) {
return detail::process_client_socket(socket.sock, read_timeout_sec_, return detail::process_client_socket(
read_timeout_usec_, write_timeout_sec_, socket.sock, read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
write_timeout_usec_, write_timeout_usec_, std::move(callback));
std::move(callback));
} }
inline bool ClientImpl::is_ssl() const { return false; } inline bool ClientImpl::is_ssl() const { return false; }
@ -5306,10 +5308,9 @@ inline Result ClientImpl::Post(const char *path, const Headers &headers,
size_t content_length, size_t content_length,
ContentProvider content_provider, ContentProvider content_provider,
const char *content_type) { const char *content_type) {
auto ret = send_with_content_provider("POST", path, headers, std::string(), auto ret = send_with_content_provider(
content_length, "POST", path, headers, std::string(), content_length,
std::move(content_provider), std::move(content_provider), content_type);
content_type);
return Result{std::move(ret), get_last_error()}; return Result{std::move(ret), get_last_error()};
} }
@ -5330,7 +5331,7 @@ inline Result ClientImpl::Post(const char *path, const Headers &headers,
} }
inline Result ClientImpl::Post(const char *path, const Headers &headers, inline Result ClientImpl::Post(const char *path, const Headers &headers,
const MultipartFormDataItems &items, const MultipartFormDataItems &items,
const std::string& boundary) { const std::string &boundary) {
for (size_t i = 0; i < boundary.size(); i++) { for (size_t i = 0; i < boundary.size(); i++) {
char c = boundary[i]; char c = boundary[i];
if (!std::isalnum(c) && c != '-' && c != '_') { if (!std::isalnum(c) && c != '-' && c != '_') {
@ -5389,10 +5390,9 @@ inline Result ClientImpl::Put(const char *path, const Headers &headers,
size_t content_length, size_t content_length,
ContentProvider content_provider, ContentProvider content_provider,
const char *content_type) { const char *content_type) {
auto ret = send_with_content_provider("PUT", path, headers, std::string(), auto ret = send_with_content_provider(
content_length, "PUT", path, headers, std::string(), content_length,
std::move(content_provider), std::move(content_provider), content_type);
content_type);
return Result{std::move(ret), get_last_error()}; return Result{std::move(ret), get_last_error()};
} }
@ -5430,10 +5430,9 @@ inline Result ClientImpl::Patch(const char *path, const Headers &headers,
size_t content_length, size_t content_length,
ContentProvider content_provider, ContentProvider content_provider,
const char *content_type) { const char *content_type) {
auto ret = send_with_content_provider("PATCH", path, headers, std::string(), auto ret = send_with_content_provider(
content_length, "PATCH", path, headers, std::string(), content_length,
std::move(content_provider), std::move(content_provider), content_type);
content_type);
return Result{std::move(ret), get_last_error()}; return Result{std::move(ret), get_last_error()};
} }
@ -6381,7 +6380,7 @@ inline Result Client::Post(const char *path, const Headers &headers,
} }
inline Result Client::Post(const char *path, const Headers &headers, inline Result Client::Post(const char *path, const Headers &headers,
const MultipartFormDataItems &items, const MultipartFormDataItems &items,
const std::string& boundary) { const std::string &boundary) {
return cli_->Post(path, headers, items, boundary); return cli_->Post(path, headers, items, boundary);
} }
inline Result Client::Put(const char *path) { return cli_->Put(path); } inline Result Client::Put(const char *path) { return cli_->Put(path); }

View File

@ -1897,6 +1897,14 @@ TEST_F(ServerTest, GetStreamedWithRange2) {
EXPECT_EQ(std::string("bcdefg"), res->body); EXPECT_EQ(std::string("bcdefg"), res->body);
} }
TEST_F(ServerTest, GetStreamedWithRangeError) {
auto res = cli_.Get("/streamed-with-range", {
{"Range", "bytes=92233720368547758079223372036854775806-92233720368547758079223372036854775807"}
});
ASSERT_TRUE(res);
EXPECT_EQ(416, res->status);
}
TEST_F(ServerTest, GetStreamedWithRangeMultipart) { TEST_F(ServerTest, GetStreamedWithRangeMultipart) {
auto res = auto res =
cli_.Get("/streamed-with-range", {{make_range_header({{1, 2}, {4, 5}})}}); cli_.Get("/streamed-with-range", {{make_range_header({{1, 2}, {4, 5}})}});