mirror of
https://github.com/yhirose/cpp-httplib
synced 2024-11-21 14:29:10 -07:00
Fix #619
This commit is contained in:
parent
510b4eaaae
commit
e5903635e2
1 changed files with 33 additions and 28 deletions
61
httplib.h
61
httplib.h
|
@ -281,7 +281,7 @@ public:
|
||||||
private:
|
private:
|
||||||
class data_sink_streambuf : public std::streambuf {
|
class data_sink_streambuf : public std::streambuf {
|
||||||
public:
|
public:
|
||||||
data_sink_streambuf(DataSink &sink) : sink_(sink) {}
|
explicit data_sink_streambuf(DataSink &sink) : sink_(sink) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::streamsize xsputn(const char *s, std::streamsize n) {
|
std::streamsize xsputn(const char *s, std::streamsize n) {
|
||||||
|
@ -402,15 +402,15 @@ struct Response {
|
||||||
|
|
||||||
void set_content_provider(
|
void set_content_provider(
|
||||||
size_t length, const char *content_type, ContentProvider provider,
|
size_t length, const char *content_type, ContentProvider provider,
|
||||||
std::function<void()> resource_releaser = [] {});
|
const std::function<void()> &resource_releaser = nullptr);
|
||||||
|
|
||||||
void set_content_provider(
|
void set_content_provider(
|
||||||
const char *content_type, ContentProviderWithoutLength provider,
|
const char *content_type, ContentProviderWithoutLength provider,
|
||||||
std::function<void()> resource_releaser = [] {});
|
const std::function<void()> &resource_releaser = nullptr);
|
||||||
|
|
||||||
void set_chunked_content_provider(
|
void set_chunked_content_provider(
|
||||||
const char *content_type, ContentProviderWithoutLength provider,
|
const char *content_type, ContentProviderWithoutLength provider,
|
||||||
std::function<void()> resource_releaser = [] {});
|
const std::function<void()> &resource_releaser = nullptr);
|
||||||
|
|
||||||
Response() = default;
|
Response() = default;
|
||||||
Response(const Response &) = default;
|
Response(const Response &) = default;
|
||||||
|
@ -634,10 +634,11 @@ private:
|
||||||
|
|
||||||
bool routing(Request &req, Response &res, Stream &strm);
|
bool routing(Request &req, Response &res, Stream &strm);
|
||||||
bool handle_file_request(Request &req, Response &res, bool head = false);
|
bool handle_file_request(Request &req, Response &res, bool head = false);
|
||||||
bool dispatch_request(Request &req, Response &res, Handlers &handlers);
|
bool dispatch_request(Request &req, Response &res, const Handlers &handlers);
|
||||||
bool dispatch_request_for_content_reader(Request &req, Response &res,
|
bool
|
||||||
ContentReader content_reader,
|
dispatch_request_for_content_reader(Request &req, Response &res,
|
||||||
HandlersForContentReader &handlers);
|
ContentReader content_reader,
|
||||||
|
const HandlersForContentReader &handlers);
|
||||||
|
|
||||||
bool parse_request_line(const char *s, Request &req);
|
bool parse_request_line(const char *s, Request &req);
|
||||||
bool write_response(Stream &strm, bool close_connection, const Request &req,
|
bool write_response(Stream &strm, bool close_connection, const Request &req,
|
||||||
|
@ -696,7 +697,8 @@ enum Error {
|
||||||
|
|
||||||
class Result {
|
class Result {
|
||||||
public:
|
public:
|
||||||
Result(std::shared_ptr<Response> res, Error err) : res_(res), err_(err) {}
|
Result(const std::shared_ptr<Response> &res, Error err)
|
||||||
|
: res_(res), err_(err) {}
|
||||||
operator bool() const { return res_ != nullptr; }
|
operator bool() const { return res_ != nullptr; }
|
||||||
bool operator==(std::nullptr_t) const { return res_ == nullptr; }
|
bool operator==(std::nullptr_t) const { return res_ == nullptr; }
|
||||||
bool operator!=(std::nullptr_t) const { return res_ != nullptr; }
|
bool operator!=(std::nullptr_t) const { return res_ != nullptr; }
|
||||||
|
@ -899,7 +901,7 @@ protected:
|
||||||
std::string interface_;
|
std::string interface_;
|
||||||
|
|
||||||
std::string proxy_host_;
|
std::string proxy_host_;
|
||||||
int proxy_port_;
|
int proxy_port_ = -1;
|
||||||
|
|
||||||
std::string proxy_basic_auth_username_;
|
std::string proxy_basic_auth_username_;
|
||||||
std::string proxy_basic_auth_password_;
|
std::string proxy_basic_auth_password_;
|
||||||
|
@ -1971,7 +1973,7 @@ inline socket_t create_client_socket(const char *host, int port,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (sock != INVALID_SOCKET) {
|
if (sock != INVALID_SOCKET) {
|
||||||
if (error != Error::Success) { error = Error::Success; }
|
error = Error::Success;
|
||||||
} else {
|
} else {
|
||||||
if (error == Error::Success) { error = Error::Connection; }
|
if (error == Error::Success) { error = Error::Connection; }
|
||||||
}
|
}
|
||||||
|
@ -2607,7 +2609,7 @@ 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, receiver, decompress, [&](ContentReceiver &out) {
|
x, status, receiver, decompress, [&](const ContentReceiver &out) {
|
||||||
auto ret = true;
|
auto ret = true;
|
||||||
auto exceed_payload_max_length = false;
|
auto exceed_payload_max_length = false;
|
||||||
|
|
||||||
|
@ -2835,7 +2837,7 @@ inline std::string params_to_query_str(const Params ¶ms) {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void parse_query_text(const std::string &s, Params ¶ms) {
|
inline void parse_query_text(const std::string &s, Params ¶ms) {
|
||||||
split(&s[0], &s[s.size()], '&', [&](const char *b, const char *e) {
|
split(s.data(), s.data() + s.size(), '&', [&](const char *b, const char *e) {
|
||||||
std::string key;
|
std::string key;
|
||||||
std::string val;
|
std::string val;
|
||||||
split(b, e, '=', [&](const char *b2, const char *e2) {
|
split(b, e, '=', [&](const char *b2, const char *e2) {
|
||||||
|
@ -3019,14 +3021,14 @@ public:
|
||||||
}
|
}
|
||||||
case 4: { // Boundary
|
case 4: { // Boundary
|
||||||
if (crlf_.size() > buf_.size()) { return true; }
|
if (crlf_.size() > buf_.size()) { return true; }
|
||||||
if (buf_.find(crlf_) == 0) {
|
if (buf_.compare(0, crlf_.size(), crlf_) == 0) {
|
||||||
buf_.erase(0, crlf_.size());
|
buf_.erase(0, crlf_.size());
|
||||||
off_ += crlf_.size();
|
off_ += crlf_.size();
|
||||||
state_ = 1;
|
state_ = 1;
|
||||||
} else {
|
} else {
|
||||||
auto pattern = dash_ + crlf_;
|
auto pattern = dash_ + crlf_;
|
||||||
if (pattern.size() > buf_.size()) { return true; }
|
if (pattern.size() > buf_.size()) { return true; }
|
||||||
if (buf_.find(pattern) == 0) {
|
if (buf_.compare(0, pattern.size(), pattern) == 0) {
|
||||||
buf_.erase(0, pattern.size());
|
buf_.erase(0, pattern.size());
|
||||||
off_ += pattern.size();
|
off_ += pattern.size();
|
||||||
is_valid_ = true;
|
is_valid_ = true;
|
||||||
|
@ -3568,7 +3570,7 @@ inline void Response::set_content(std::string s, const char *content_type) {
|
||||||
inline void
|
inline void
|
||||||
Response::set_content_provider(size_t in_length, const char *content_type,
|
Response::set_content_provider(size_t in_length, const char *content_type,
|
||||||
ContentProvider provider,
|
ContentProvider provider,
|
||||||
std::function<void()> resource_releaser) {
|
const std::function<void()> &resource_releaser) {
|
||||||
assert(in_length > 0);
|
assert(in_length > 0);
|
||||||
set_header("Content-Type", content_type);
|
set_header("Content-Type", content_type);
|
||||||
content_length_ = in_length;
|
content_length_ = in_length;
|
||||||
|
@ -3579,9 +3581,10 @@ Response::set_content_provider(size_t in_length, const char *content_type,
|
||||||
is_chunked_content_provider = false;
|
is_chunked_content_provider = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Response::set_content_provider(
|
inline void
|
||||||
const char *content_type, ContentProviderWithoutLength provider,
|
Response::set_content_provider(const char *content_type,
|
||||||
std::function<void()> resource_releaser) {
|
ContentProviderWithoutLength provider,
|
||||||
|
const std::function<void()> &resource_releaser) {
|
||||||
set_header("Content-Type", content_type);
|
set_header("Content-Type", content_type);
|
||||||
content_length_ = 0;
|
content_length_ = 0;
|
||||||
content_provider_ = [provider](size_t offset, size_t, DataSink &sink) {
|
content_provider_ = [provider](size_t offset, size_t, DataSink &sink) {
|
||||||
|
@ -3593,7 +3596,7 @@ inline void Response::set_content_provider(
|
||||||
|
|
||||||
inline void Response::set_chunked_content_provider(
|
inline void Response::set_chunked_content_provider(
|
||||||
const char *content_type, ContentProviderWithoutLength provider,
|
const char *content_type, ContentProviderWithoutLength provider,
|
||||||
std::function<void()> resource_releaser) {
|
const std::function<void()> &resource_releaser) {
|
||||||
set_header("Content-Type", content_type);
|
set_header("Content-Type", content_type);
|
||||||
content_length_ = 0;
|
content_length_ = 0;
|
||||||
content_provider_ = [provider](size_t offset, size_t, DataSink &sink) {
|
content_provider_ = [provider](size_t offset, size_t, DataSink &sink) {
|
||||||
|
@ -3727,11 +3730,13 @@ inline const std::string &BufferStream::get_buffer() const { return buffer; }
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
// HTTP server implementation
|
// HTTP server implementation
|
||||||
inline Server::Server() : svr_sock_(INVALID_SOCKET), is_running_(false) {
|
inline Server::Server()
|
||||||
|
: new_task_queue(
|
||||||
|
[] { return new ThreadPool(CPPHTTPLIB_THREAD_POOL_COUNT); }),
|
||||||
|
svr_sock_(INVALID_SOCKET), is_running_(false) {
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
#endif
|
#endif
|
||||||
new_task_queue = [] { return new ThreadPool(CPPHTTPLIB_THREAD_POOL_COUNT); };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Server::~Server() {}
|
inline Server::~Server() {}
|
||||||
|
@ -4233,7 +4238,7 @@ inline bool Server::handle_file_request(Request &req, Response &res,
|
||||||
const auto &base_dir = kv.second;
|
const auto &base_dir = kv.second;
|
||||||
|
|
||||||
// Prefix match
|
// Prefix match
|
||||||
if (!req.path.find(mount_point)) {
|
if (!req.path.compare(0, mount_point.size(), mount_point)) {
|
||||||
std::string sub_path = "/" + req.path.substr(mount_point.size());
|
std::string sub_path = "/" + req.path.substr(mount_point.size());
|
||||||
if (detail::is_valid_path(sub_path)) {
|
if (detail::is_valid_path(sub_path)) {
|
||||||
auto path = base_dir + sub_path;
|
auto path = base_dir + sub_path;
|
||||||
|
@ -4417,7 +4422,7 @@ inline bool Server::routing(Request &req, Response &res, Stream &strm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Server::dispatch_request(Request &req, Response &res,
|
inline bool Server::dispatch_request(Request &req, Response &res,
|
||||||
Handlers &handlers) {
|
const Handlers &handlers) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (const auto &x : handlers) {
|
for (const auto &x : handlers) {
|
||||||
|
@ -4441,7 +4446,7 @@ inline bool Server::dispatch_request(Request &req, Response &res,
|
||||||
|
|
||||||
inline bool Server::dispatch_request_for_content_reader(
|
inline bool Server::dispatch_request_for_content_reader(
|
||||||
Request &req, Response &res, ContentReader content_reader,
|
Request &req, Response &res, ContentReader content_reader,
|
||||||
HandlersForContentReader &handlers) {
|
const HandlersForContentReader &handlers) {
|
||||||
for (const auto &x : handlers) {
|
for (const auto &x : handlers) {
|
||||||
const auto &pattern = x.first;
|
const auto &pattern = x.first;
|
||||||
const auto &handler = x.second;
|
const auto &handler = x.second;
|
||||||
|
@ -4569,7 +4574,7 @@ inline bool ClientImpl::is_valid() const { return true; }
|
||||||
inline Error ClientImpl::get_last_error() const { return error_; }
|
inline Error ClientImpl::get_last_error() const { return error_; }
|
||||||
|
|
||||||
inline socket_t ClientImpl::create_client_socket() const {
|
inline socket_t ClientImpl::create_client_socket() const {
|
||||||
if (!proxy_host_.empty()) {
|
if (!proxy_host_.empty() && proxy_port_ != -1) {
|
||||||
return detail::create_client_socket(
|
return detail::create_client_socket(
|
||||||
proxy_host_.c_str(), proxy_port_, tcp_nodelay_, socket_options_,
|
proxy_host_.c_str(), proxy_port_, tcp_nodelay_, socket_options_,
|
||||||
connection_timeout_sec_, connection_timeout_usec_, interface_, error_);
|
connection_timeout_sec_, connection_timeout_usec_, interface_, error_);
|
||||||
|
@ -4632,7 +4637,7 @@ inline bool ClientImpl::send(const Request &req, Response &res) {
|
||||||
// TODO: refactoring
|
// TODO: refactoring
|
||||||
if (is_ssl()) {
|
if (is_ssl()) {
|
||||||
auto &scli = static_cast<SSLClient &>(*this);
|
auto &scli = static_cast<SSLClient &>(*this);
|
||||||
if (!proxy_host_.empty()) {
|
if (!proxy_host_.empty() && proxy_port_ != -1) {
|
||||||
bool success = false;
|
bool success = false;
|
||||||
if (!scli.connect_with_proxy(socket_, res, success)) {
|
if (!scli.connect_with_proxy(socket_, res, success)) {
|
||||||
return success;
|
return success;
|
||||||
|
@ -4669,7 +4674,7 @@ inline bool ClientImpl::handle_request(Stream &strm, const Request &req,
|
||||||
|
|
||||||
bool ret;
|
bool ret;
|
||||||
|
|
||||||
if (!is_ssl() && !proxy_host_.empty()) {
|
if (!is_ssl() && !proxy_host_.empty() && proxy_port_ != -1) {
|
||||||
auto req2 = req;
|
auto req2 = req;
|
||||||
req2.path = "http://" + host_and_port_ + req.path;
|
req2.path = "http://" + host_and_port_ + req.path;
|
||||||
ret = process_request(strm, req2, res, close_connection);
|
ret = process_request(strm, req2, res, close_connection);
|
||||||
|
|
Loading…
Reference in a new issue