mirror of
https://github.com/yhirose/cpp-httplib
synced 2026-06-08 18:30:49 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ccbddd8842 | |||
| 879dd261c2 | |||
| 52f5eb5980 | |||
| ea2f69a0d7 | |||
| 9f2064a8ed | |||
| e3750d9ddf | |||
| c1eee3012e | |||
| 6b08babbd2 |
@@ -624,35 +624,22 @@ public:
|
||||
|
||||
virtual bool is_valid() const;
|
||||
|
||||
Server &Get(const char *pattern, Handler handler);
|
||||
Server &Get(const char *pattern, size_t pattern_len, Handler handler);
|
||||
Server &Post(const char *pattern, Handler handler);
|
||||
Server &Post(const char *pattern, size_t pattern_len, Handler handler);
|
||||
Server &Post(const char *pattern, HandlerWithContentReader handler);
|
||||
Server &Post(const char *pattern, size_t pattern_len,
|
||||
HandlerWithContentReader handler);
|
||||
Server &Put(const char *pattern, Handler handler);
|
||||
Server &Put(const char *pattern, size_t pattern_len, Handler handler);
|
||||
Server &Put(const char *pattern, HandlerWithContentReader handler);
|
||||
Server &Put(const char *pattern, size_t pattern_len,
|
||||
HandlerWithContentReader handler);
|
||||
Server &Patch(const char *pattern, Handler handler);
|
||||
Server &Patch(const char *pattern, size_t pattern_len, Handler handler);
|
||||
Server &Patch(const char *pattern, HandlerWithContentReader handler);
|
||||
Server &Patch(const char *pattern, size_t pattern_len,
|
||||
HandlerWithContentReader handler);
|
||||
Server &Delete(const char *pattern, Handler handler);
|
||||
Server &Delete(const char *pattern, size_t pattern_len, Handler handler);
|
||||
Server &Delete(const char *pattern, HandlerWithContentReader handler);
|
||||
Server &Delete(const char *pattern, size_t pattern_len,
|
||||
HandlerWithContentReader handler);
|
||||
Server &Options(const char *pattern, Handler handler);
|
||||
Server &Options(const char *pattern, size_t pattern_len, Handler handler);
|
||||
Server &Get(const std::string &pattern, Handler handler);
|
||||
Server &Post(const std::string &pattern, Handler handler);
|
||||
Server &Post(const std::string &pattern, HandlerWithContentReader handler);
|
||||
Server &Put(const std::string &pattern, Handler handler);
|
||||
Server &Put(const std::string &pattern, HandlerWithContentReader handler);
|
||||
Server &Patch(const std::string &pattern, Handler handler);
|
||||
Server &Patch(const std::string &pattern, HandlerWithContentReader handler);
|
||||
Server &Delete(const std::string &pattern, Handler handler);
|
||||
Server &Delete(const std::string &pattern, HandlerWithContentReader handler);
|
||||
Server &Options(const std::string &pattern, Handler handler);
|
||||
|
||||
bool set_base_dir(const char *dir, const char *mount_point = nullptr);
|
||||
bool set_mount_point(const char *mount_point, const char *dir,
|
||||
bool set_base_dir(const std::string &dir,
|
||||
const std::string &mount_point = nullptr);
|
||||
bool set_mount_point(const std::string &mount_point, const std::string &dir,
|
||||
Headers headers = Headers());
|
||||
bool remove_mount_point(const char *mount_point);
|
||||
bool remove_mount_point(const std::string &mount_point);
|
||||
Server &set_file_extension_and_mimetype_mapping(const char *ext,
|
||||
const char *mime);
|
||||
Server &set_file_request_handler(Handler handler);
|
||||
@@ -811,8 +798,31 @@ enum class Error {
|
||||
Compression,
|
||||
};
|
||||
|
||||
inline std::string to_string(const Error error) {
|
||||
switch (error) {
|
||||
case Error::Success: return "Success";
|
||||
case Error::Connection: return "Connection";
|
||||
case Error::BindIPAddress: return "BindIPAddress";
|
||||
case Error::Read: return "Read";
|
||||
case Error::Write: return "Write";
|
||||
case Error::ExceedRedirectCount: return "ExceedRedirectCount";
|
||||
case Error::Canceled: return "Canceled";
|
||||
case Error::SSLConnection: return "SSLConnection";
|
||||
case Error::SSLLoadingCerts: return "SSLLoadingCerts";
|
||||
case Error::SSLServerVerification: return "SSLServerVerification";
|
||||
case Error::UnsupportedMultipartBoundaryChars:
|
||||
return "UnsupportedMultipartBoundaryChars";
|
||||
case Error::Compression: return "Compression";
|
||||
case Error::Unknown: return "Unknown";
|
||||
default: break;
|
||||
}
|
||||
|
||||
return "Invalid";
|
||||
}
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &os, const Error &obj) {
|
||||
os << static_cast<std::underlying_type<Error>::type>(obj);
|
||||
os << to_string(obj);
|
||||
os << " (" << static_cast<std::underlying_type<Error>::type>(obj) << ')';
|
||||
return os;
|
||||
}
|
||||
|
||||
@@ -1026,6 +1036,12 @@ public:
|
||||
void set_proxy_digest_auth(const char *username, const char *password);
|
||||
#endif
|
||||
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
void set_ca_cert_path(const char *ca_cert_file_path,
|
||||
const char *ca_cert_dir_path = nullptr);
|
||||
void set_ca_cert_store(X509_STORE *ca_cert_store);
|
||||
#endif
|
||||
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
void enable_server_certificate_verification(bool enabled);
|
||||
#endif
|
||||
@@ -1127,6 +1143,13 @@ protected:
|
||||
std::string proxy_digest_auth_password_;
|
||||
#endif
|
||||
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
std::string ca_cert_file_path_;
|
||||
std::string ca_cert_dir_path_;
|
||||
|
||||
X509_STORE *ca_cert_store_ = nullptr;
|
||||
#endif
|
||||
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
bool server_certificate_verification_ = true;
|
||||
#endif
|
||||
@@ -1153,6 +1176,8 @@ private:
|
||||
ContentProviderWithoutLength content_provider_without_length,
|
||||
const char *content_type);
|
||||
|
||||
std::string adjust_host_string(const std::string &host) const;
|
||||
|
||||
virtual bool process_socket(const Socket &socket,
|
||||
std::function<bool(Stream &strm)> callback);
|
||||
virtual bool is_ssl() const;
|
||||
@@ -1161,9 +1186,9 @@ private:
|
||||
class Client {
|
||||
public:
|
||||
// Universal interface
|
||||
explicit Client(const char *scheme_host_port);
|
||||
explicit Client(const std::string &scheme_host_port);
|
||||
|
||||
explicit Client(const char *scheme_host_port,
|
||||
explicit Client(const std::string &scheme_host_port,
|
||||
const std::string &client_cert_path,
|
||||
const std::string &client_key_path);
|
||||
|
||||
@@ -1403,9 +1428,6 @@ public:
|
||||
|
||||
bool is_valid() const override;
|
||||
|
||||
void set_ca_cert_path(const char *ca_cert_file_path,
|
||||
const char *ca_cert_dir_path = nullptr);
|
||||
|
||||
void set_ca_cert_store(X509_STORE *ca_cert_store);
|
||||
|
||||
long get_openssl_verify_result() const;
|
||||
@@ -1438,8 +1460,6 @@ private:
|
||||
|
||||
std::vector<std::string> host_components_;
|
||||
|
||||
std::string ca_cert_file_path_;
|
||||
std::string ca_cert_dir_path_;
|
||||
long verify_result_ = 0;
|
||||
|
||||
friend class ClientImpl;
|
||||
@@ -2558,28 +2578,40 @@ public:
|
||||
Callback callback) override {
|
||||
assert(is_valid_);
|
||||
|
||||
auto flush = last ? Z_FINISH : Z_NO_FLUSH;
|
||||
|
||||
strm_.avail_in = static_cast<decltype(strm_.avail_in)>(data_length);
|
||||
strm_.next_in = const_cast<Bytef *>(reinterpret_cast<const Bytef *>(data));
|
||||
|
||||
int ret = Z_OK;
|
||||
|
||||
std::array<char, CPPHTTPLIB_COMPRESSION_BUFSIZ> buff{};
|
||||
do {
|
||||
strm_.avail_out = static_cast<uInt>(buff.size());
|
||||
strm_.next_out = reinterpret_cast<Bytef *>(buff.data());
|
||||
constexpr size_t max_avail_in =
|
||||
std::numeric_limits<decltype(strm_.avail_in)>::max();
|
||||
|
||||
ret = deflate(&strm_, flush);
|
||||
if (ret == Z_STREAM_ERROR) { return false; }
|
||||
strm_.avail_in = static_cast<decltype(strm_.avail_in)>(
|
||||
std::min(data_length, max_avail_in));
|
||||
strm_.next_in =
|
||||
const_cast<Bytef *>(reinterpret_cast<const Bytef *>(data));
|
||||
|
||||
if (!callback(buff.data(), buff.size() - strm_.avail_out)) {
|
||||
return false;
|
||||
}
|
||||
} while (strm_.avail_out == 0);
|
||||
data_length -= strm_.avail_in;
|
||||
data += strm_.avail_in;
|
||||
|
||||
auto flush = (last && data_length == 0) ? Z_FINISH : Z_NO_FLUSH;
|
||||
int ret = Z_OK;
|
||||
|
||||
std::array<char, CPPHTTPLIB_COMPRESSION_BUFSIZ> buff{};
|
||||
do {
|
||||
strm_.avail_out = static_cast<uInt>(buff.size());
|
||||
strm_.next_out = reinterpret_cast<Bytef *>(buff.data());
|
||||
|
||||
ret = deflate(&strm_, flush);
|
||||
if (ret == Z_STREAM_ERROR) { return false; }
|
||||
|
||||
if (!callback(buff.data(), buff.size() - strm_.avail_out)) {
|
||||
return false;
|
||||
}
|
||||
} while (strm_.avail_out == 0);
|
||||
|
||||
assert((flush == Z_FINISH && ret == Z_STREAM_END) ||
|
||||
(flush == Z_NO_FLUSH && ret == Z_OK));
|
||||
assert(strm_.avail_in == 0);
|
||||
|
||||
} while (data_length > 0);
|
||||
|
||||
assert((last && ret == Z_STREAM_END) || (!last && ret == Z_OK));
|
||||
assert(strm_.avail_in == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2613,28 +2645,41 @@ public:
|
||||
|
||||
int ret = Z_OK;
|
||||
|
||||
strm_.avail_in = static_cast<decltype(strm_.avail_in)>(data_length);
|
||||
strm_.next_in = const_cast<Bytef *>(reinterpret_cast<const Bytef *>(data));
|
||||
do {
|
||||
constexpr size_t max_avail_in =
|
||||
std::numeric_limits<decltype(strm_.avail_in)>::max();
|
||||
|
||||
std::array<char, CPPHTTPLIB_COMPRESSION_BUFSIZ> buff{};
|
||||
while (strm_.avail_in > 0) {
|
||||
strm_.avail_out = static_cast<uInt>(buff.size());
|
||||
strm_.next_out = reinterpret_cast<Bytef *>(buff.data());
|
||||
strm_.avail_in = static_cast<decltype(strm_.avail_in)>(
|
||||
std::min(data_length, max_avail_in));
|
||||
strm_.next_in =
|
||||
const_cast<Bytef *>(reinterpret_cast<const Bytef *>(data));
|
||||
|
||||
ret = inflate(&strm_, Z_NO_FLUSH);
|
||||
assert(ret != Z_STREAM_ERROR);
|
||||
switch (ret) {
|
||||
case Z_NEED_DICT:
|
||||
case Z_DATA_ERROR:
|
||||
case Z_MEM_ERROR: inflateEnd(&strm_); return false;
|
||||
data_length -= strm_.avail_in;
|
||||
data += strm_.avail_in;
|
||||
|
||||
std::array<char, CPPHTTPLIB_COMPRESSION_BUFSIZ> buff{};
|
||||
while (strm_.avail_in > 0) {
|
||||
strm_.avail_out = static_cast<uInt>(buff.size());
|
||||
strm_.next_out = reinterpret_cast<Bytef *>(buff.data());
|
||||
|
||||
ret = inflate(&strm_, Z_NO_FLUSH);
|
||||
assert(ret != Z_STREAM_ERROR);
|
||||
switch (ret) {
|
||||
case Z_NEED_DICT:
|
||||
case Z_DATA_ERROR:
|
||||
case Z_MEM_ERROR: inflateEnd(&strm_); return false;
|
||||
}
|
||||
|
||||
if (!callback(buff.data(), buff.size() - strm_.avail_out)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!callback(buff.data(), buff.size() - strm_.avail_out)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (ret != Z_OK && ret != Z_STREAM_END) return false;
|
||||
|
||||
return ret == Z_OK || ret == Z_STREAM_END;
|
||||
} while (data_length > 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -4225,128 +4270,79 @@ inline Server::Server()
|
||||
|
||||
inline Server::~Server() {}
|
||||
|
||||
inline Server &Server::Get(const char *pattern, Handler handler) {
|
||||
return Get(pattern, strlen(pattern), handler);
|
||||
}
|
||||
|
||||
inline Server &Server::Get(const char *pattern, size_t pattern_len,
|
||||
Handler handler) {
|
||||
inline Server &Server::Get(const std::string &pattern, Handler handler) {
|
||||
get_handlers_.push_back(
|
||||
std::make_pair(std::regex(pattern, pattern_len), std::move(handler)));
|
||||
std::make_pair(std::regex(pattern), std::move(handler)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Server &Server::Post(const char *pattern, Handler handler) {
|
||||
return Post(pattern, strlen(pattern), handler);
|
||||
}
|
||||
|
||||
inline Server &Server::Post(const char *pattern, size_t pattern_len,
|
||||
Handler handler) {
|
||||
inline Server &Server::Post(const std::string &pattern, Handler handler) {
|
||||
post_handlers_.push_back(
|
||||
std::make_pair(std::regex(pattern, pattern_len), std::move(handler)));
|
||||
std::make_pair(std::regex(pattern), std::move(handler)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Server &Server::Post(const char *pattern,
|
||||
HandlerWithContentReader handler) {
|
||||
return Post(pattern, strlen(pattern), handler);
|
||||
}
|
||||
|
||||
inline Server &Server::Post(const char *pattern, size_t pattern_len,
|
||||
inline Server &Server::Post(const std::string &pattern,
|
||||
HandlerWithContentReader handler) {
|
||||
post_handlers_for_content_reader_.push_back(
|
||||
std::make_pair(std::regex(pattern, pattern_len), std::move(handler)));
|
||||
std::make_pair(std::regex(pattern), std::move(handler)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Server &Server::Put(const char *pattern, Handler handler) {
|
||||
return Put(pattern, strlen(pattern), handler);
|
||||
}
|
||||
|
||||
inline Server &Server::Put(const char *pattern, size_t pattern_len,
|
||||
Handler handler) {
|
||||
inline Server &Server::Put(const std::string &pattern, Handler handler) {
|
||||
put_handlers_.push_back(
|
||||
std::make_pair(std::regex(pattern, pattern_len), std::move(handler)));
|
||||
std::make_pair(std::regex(pattern), std::move(handler)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Server &Server::Put(const char *pattern,
|
||||
HandlerWithContentReader handler) {
|
||||
return Put(pattern, strlen(pattern), handler);
|
||||
}
|
||||
|
||||
inline Server &Server::Put(const char *pattern, size_t pattern_len,
|
||||
inline Server &Server::Put(const std::string &pattern,
|
||||
HandlerWithContentReader handler) {
|
||||
put_handlers_for_content_reader_.push_back(
|
||||
std::make_pair(std::regex(pattern, pattern_len), std::move(handler)));
|
||||
std::make_pair(std::regex(pattern), std::move(handler)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Server &Server::Patch(const char *pattern, Handler handler) {
|
||||
return Patch(pattern, strlen(pattern), handler);
|
||||
}
|
||||
|
||||
inline Server &Server::Patch(const char *pattern, size_t pattern_len,
|
||||
Handler handler) {
|
||||
inline Server &Server::Patch(const std::string &pattern, Handler handler) {
|
||||
patch_handlers_.push_back(
|
||||
std::make_pair(std::regex(pattern, pattern_len), std::move(handler)));
|
||||
std::make_pair(std::regex(pattern), std::move(handler)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Server &Server::Patch(const char *pattern,
|
||||
HandlerWithContentReader handler) {
|
||||
return Patch(pattern, strlen(pattern), handler);
|
||||
}
|
||||
|
||||
inline Server &Server::Patch(const char *pattern, size_t pattern_len,
|
||||
inline Server &Server::Patch(const std::string &pattern,
|
||||
HandlerWithContentReader handler) {
|
||||
patch_handlers_for_content_reader_.push_back(
|
||||
std::make_pair(std::regex(pattern, pattern_len), std::move(handler)));
|
||||
std::make_pair(std::regex(pattern), std::move(handler)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Server &Server::Delete(const char *pattern, Handler handler) {
|
||||
return Delete(pattern, strlen(pattern), handler);
|
||||
}
|
||||
|
||||
inline Server &Server::Delete(const char *pattern, size_t pattern_len,
|
||||
Handler handler) {
|
||||
inline Server &Server::Delete(const std::string &pattern, Handler handler) {
|
||||
delete_handlers_.push_back(
|
||||
std::make_pair(std::regex(pattern, pattern_len), std::move(handler)));
|
||||
std::make_pair(std::regex(pattern), std::move(handler)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Server &Server::Delete(const char *pattern,
|
||||
HandlerWithContentReader handler) {
|
||||
return Delete(pattern, strlen(pattern), handler);
|
||||
}
|
||||
|
||||
inline Server &Server::Delete(const char *pattern, size_t pattern_len,
|
||||
inline Server &Server::Delete(const std::string &pattern,
|
||||
HandlerWithContentReader handler) {
|
||||
delete_handlers_for_content_reader_.push_back(
|
||||
std::make_pair(std::regex(pattern, pattern_len), std::move(handler)));
|
||||
std::make_pair(std::regex(pattern), std::move(handler)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Server &Server::Options(const char *pattern, Handler handler) {
|
||||
return Options(pattern, strlen(pattern), handler);
|
||||
}
|
||||
|
||||
inline Server &Server::Options(const char *pattern, size_t pattern_len,
|
||||
Handler handler) {
|
||||
inline Server &Server::Options(const std::string &pattern, Handler handler) {
|
||||
options_handlers_.push_back(
|
||||
std::make_pair(std::regex(pattern, pattern_len), std::move(handler)));
|
||||
std::make_pair(std::regex(pattern), std::move(handler)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool Server::set_base_dir(const char *dir, const char *mount_point) {
|
||||
inline bool Server::set_base_dir(const std::string &dir,
|
||||
const std::string &mount_point) {
|
||||
return set_mount_point(mount_point, dir);
|
||||
}
|
||||
|
||||
inline bool Server::set_mount_point(const char *mount_point, const char *dir,
|
||||
Headers headers) {
|
||||
inline bool Server::set_mount_point(const std::string &mount_point,
|
||||
const std::string &dir, Headers headers) {
|
||||
if (detail::is_dir(dir)) {
|
||||
std::string mnt = mount_point ? mount_point : "/";
|
||||
std::string mnt = !mount_point.empty() ? mount_point : "/";
|
||||
if (!mnt.empty() && mnt[0] == '/') {
|
||||
base_dirs_.push_back({mnt, dir, std::move(headers)});
|
||||
return true;
|
||||
@@ -4355,7 +4351,7 @@ inline bool Server::set_mount_point(const char *mount_point, const char *dir,
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool Server::remove_mount_point(const char *mount_point) {
|
||||
inline bool Server::remove_mount_point(const std::string &mount_point) {
|
||||
for (auto it = base_dirs_.begin(); it != base_dirs_.end(); ++it) {
|
||||
if (it->mount_point == mount_point) {
|
||||
base_dirs_.erase(it);
|
||||
@@ -5301,9 +5297,8 @@ inline ClientImpl::ClientImpl(const std::string &host, int port)
|
||||
inline ClientImpl::ClientImpl(const std::string &host, int port,
|
||||
const std::string &client_cert_path,
|
||||
const std::string &client_key_path)
|
||||
// : (Error::Success), host_(host), port_(port),
|
||||
: host_(host), port_(port),
|
||||
host_and_port_(host_ + ":" + std::to_string(port_)),
|
||||
host_and_port_(adjust_host_string(host) + ":" + std::to_string(port)),
|
||||
client_cert_path_(client_cert_path), client_key_path_(client_key_path) {}
|
||||
|
||||
inline ClientImpl::~ClientImpl() {
|
||||
@@ -5347,6 +5342,11 @@ inline void ClientImpl::copy_settings(const ClientImpl &rhs) {
|
||||
proxy_digest_auth_username_ = rhs.proxy_digest_auth_username_;
|
||||
proxy_digest_auth_password_ = rhs.proxy_digest_auth_password_;
|
||||
#endif
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
ca_cert_file_path_ = rhs.ca_cert_file_path_;
|
||||
ca_cert_dir_path_ = rhs.ca_cert_dir_path_;
|
||||
ca_cert_store_ = rhs.ca_cert_store_;
|
||||
#endif
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
server_certificate_verification_ = rhs.server_certificate_verification_;
|
||||
#endif
|
||||
@@ -5642,6 +5642,9 @@ inline bool ClientImpl::redirect(Request &req, Response &res, Error &error) {
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
SSLClient cli(next_host.c_str(), next_port);
|
||||
cli.copy_settings(*this);
|
||||
if (ca_cert_store_) {
|
||||
cli.set_ca_cert_store(ca_cert_store_);
|
||||
}
|
||||
return detail::redirect(cli, req, res, next_path, location, error);
|
||||
#else
|
||||
return false;
|
||||
@@ -5898,6 +5901,12 @@ inline Result ClientImpl::send_with_content_provider(
|
||||
return Result{std::move(res), error, std::move(req.headers)};
|
||||
}
|
||||
|
||||
inline std::string
|
||||
ClientImpl::adjust_host_string(const std::string &host) const {
|
||||
if (host.find(':') != std::string::npos) { return "[" + host + "]"; }
|
||||
return host;
|
||||
}
|
||||
|
||||
inline bool ClientImpl::process_request(Stream &strm, Request &req,
|
||||
Response &res, bool close_connection,
|
||||
Error &error) {
|
||||
@@ -6543,6 +6552,20 @@ inline void ClientImpl::set_proxy_digest_auth(const char *username,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
inline void ClientImpl::set_ca_cert_path(const char *ca_cert_file_path,
|
||||
const char *ca_cert_dir_path) {
|
||||
if (ca_cert_file_path) { ca_cert_file_path_ = ca_cert_file_path; }
|
||||
if (ca_cert_dir_path) { ca_cert_dir_path_ = ca_cert_dir_path; }
|
||||
}
|
||||
|
||||
inline void ClientImpl::set_ca_cert_store(X509_STORE *ca_cert_store) {
|
||||
if (ca_cert_store && ca_cert_store != ca_cert_store_) {
|
||||
ca_cert_store_ = ca_cert_store;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
inline void ClientImpl::enable_server_certificate_verification(bool enabled) {
|
||||
server_certificate_verification_ = enabled;
|
||||
@@ -6933,12 +6956,6 @@ inline SSLClient::~SSLClient() {
|
||||
|
||||
inline bool SSLClient::is_valid() const { return ctx_; }
|
||||
|
||||
inline void SSLClient::set_ca_cert_path(const char *ca_cert_file_path,
|
||||
const char *ca_cert_dir_path) {
|
||||
if (ca_cert_file_path) { ca_cert_file_path_ = ca_cert_file_path; }
|
||||
if (ca_cert_dir_path) { ca_cert_dir_path_ = ca_cert_dir_path; }
|
||||
}
|
||||
|
||||
inline void SSLClient::set_ca_cert_store(X509_STORE *ca_cert_store) {
|
||||
if (ca_cert_store) {
|
||||
if (ctx_) {
|
||||
@@ -7261,16 +7278,16 @@ inline bool SSLClient::check_host_name(const char *pattern,
|
||||
#endif
|
||||
|
||||
// Universal client implementation
|
||||
inline Client::Client(const char *scheme_host_port)
|
||||
inline Client::Client(const std::string &scheme_host_port)
|
||||
: Client(scheme_host_port, std::string(), std::string()) {}
|
||||
|
||||
inline Client::Client(const char *scheme_host_port,
|
||||
inline Client::Client(const std::string &scheme_host_port,
|
||||
const std::string &client_cert_path,
|
||||
const std::string &client_key_path) {
|
||||
const static std::regex re(
|
||||
R"((?:([a-z]+):\/\/)?(?:\[([\d:]+)\]|([^:/?#]+))(?::(\d+))?)");
|
||||
|
||||
std::cmatch m;
|
||||
std::smatch m;
|
||||
if (std::regex_match(scheme_host_port, m, re)) {
|
||||
auto scheme = m[1].str();
|
||||
|
||||
@@ -7681,15 +7698,14 @@ inline void Client::set_logger(Logger logger) { cli_->set_logger(logger); }
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
inline void Client::set_ca_cert_path(const char *ca_cert_file_path,
|
||||
const char *ca_cert_dir_path) {
|
||||
if (is_ssl_) {
|
||||
static_cast<SSLClient &>(*cli_).set_ca_cert_path(ca_cert_file_path,
|
||||
ca_cert_dir_path);
|
||||
}
|
||||
cli_->set_ca_cert_path(ca_cert_file_path, ca_cert_dir_path);
|
||||
}
|
||||
|
||||
inline void Client::set_ca_cert_store(X509_STORE *ca_cert_store) {
|
||||
if (is_ssl_) {
|
||||
static_cast<SSLClient &>(*cli_).set_ca_cert_store(ca_cert_store);
|
||||
} else {
|
||||
cli_->set_ca_cert_store(ca_cert_store);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
#CXX = clang++
|
||||
CXXFLAGS = -g -std=c++11 -DGTEST_USE_OWN_TR1_TUPLE -I.. -I. -Wall -Wextra -Wtype-limits -Wconversion #-fsanitize=address
|
||||
CXXFLAGS = -g -std=c++11 -I.. -I. -Wall -Wextra -Wtype-limits -Wconversion #-fsanitize=address
|
||||
|
||||
OPENSSL_DIR = /usr/local/opt/openssl@1.1
|
||||
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I$(OPENSSL_DIR)/include -L$(OPENSSL_DIR)/lib -lssl -lcrypto
|
||||
|
||||
+5790
-2421
File diff suppressed because it is too large
Load Diff
+6845
-14039
File diff suppressed because it is too large
Load Diff
@@ -27,13 +27,28 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <cstdio>
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
GTEST_API_ int main(int argc, char **argv) {
|
||||
std::cout << "Running main() from gtest_main.cc\n";
|
||||
#if GTEST_OS_ESP8266 || GTEST_OS_ESP32
|
||||
#if GTEST_OS_ESP8266
|
||||
extern "C" {
|
||||
#endif
|
||||
void setup() {
|
||||
testing::InitGoogleTest();
|
||||
}
|
||||
|
||||
void loop() { RUN_ALL_TESTS(); }
|
||||
|
||||
#if GTEST_OS_ESP8266
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
GTEST_API_ int main(int argc, char **argv) {
|
||||
printf("Running main() from %s\n", __FILE__);
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
#endif
|
||||
|
||||
+131
-45
@@ -172,7 +172,7 @@ TEST(GetHeaderValueTest, SetContent) {
|
||||
EXPECT_EQ("text/html", res.get_header_value("Content-Type"));
|
||||
|
||||
res.set_content("text", "text/plain");
|
||||
EXPECT_EQ(1, res.get_header_value_count("Content-Type"));
|
||||
EXPECT_EQ(1U, res.get_header_value_count("Content-Type"));
|
||||
EXPECT_EQ("text/plain", res.get_header_value("Content-Type"));
|
||||
}
|
||||
|
||||
@@ -542,7 +542,7 @@ TEST(ConnectionErrorTest, InvalidHostCheckResultErrorToString) {
|
||||
ASSERT_TRUE(!res);
|
||||
stringstream s;
|
||||
s << "error code: " << res.error();
|
||||
EXPECT_EQ("error code: 2", s.str());
|
||||
EXPECT_EQ("error code: Connection (2)", s.str());
|
||||
}
|
||||
|
||||
TEST(ConnectionErrorTest, InvalidPort) {
|
||||
@@ -846,7 +846,7 @@ TEST(UrlWithSpace, Redirect) {
|
||||
auto res = cli.Get("/files/2595/310/Neat 1.4-17.jar");
|
||||
ASSERT_TRUE(res);
|
||||
EXPECT_EQ(200, res->status);
|
||||
EXPECT_EQ(18527, res->get_header_value<uint64_t>("Content-Length"));
|
||||
EXPECT_EQ(18527U, res->get_header_value<uint64_t>("Content-Length"));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -954,7 +954,11 @@ TEST(RedirectFromPageWithContentIP6, Redirect) {
|
||||
res.set_redirect("http://[::1]:1234/2");
|
||||
});
|
||||
|
||||
svr.Get("/2", [&](const Request & /*req*/, Response &res) {
|
||||
svr.Get("/2", [&](const Request &req, Response &res) {
|
||||
auto host_header = req.headers.find("Host");
|
||||
ASSERT_TRUE(host_header != req.headers.end());
|
||||
EXPECT_EQ("[::1]:1234", host_header->second);
|
||||
|
||||
res.set_content("Hello World!", "text/plain");
|
||||
});
|
||||
|
||||
@@ -1222,9 +1226,9 @@ TEST(RoutingHandlerTest, PreRoutingHandler) {
|
||||
ASSERT_TRUE(res);
|
||||
EXPECT_EQ(200, res->status);
|
||||
EXPECT_EQ("Routing Handler", res->body);
|
||||
EXPECT_EQ(1, res->get_header_value_count("PRE_ROUTING"));
|
||||
EXPECT_EQ(1U, res->get_header_value_count("PRE_ROUTING"));
|
||||
EXPECT_EQ("on", res->get_header_value("PRE_ROUTING"));
|
||||
EXPECT_EQ(1, res->get_header_value_count("POST_ROUTING"));
|
||||
EXPECT_EQ(1U, res->get_header_value_count("POST_ROUTING"));
|
||||
EXPECT_EQ("on", res->get_header_value("POST_ROUTING"));
|
||||
}
|
||||
|
||||
@@ -1235,8 +1239,8 @@ TEST(RoutingHandlerTest, PreRoutingHandler) {
|
||||
ASSERT_TRUE(res);
|
||||
EXPECT_EQ(200, res->status);
|
||||
EXPECT_EQ("Hello World!\n", res->body);
|
||||
EXPECT_EQ(0, res->get_header_value_count("PRE_ROUTING"));
|
||||
EXPECT_EQ(0, res->get_header_value_count("POST_ROUTING"));
|
||||
EXPECT_EQ(0U, res->get_header_value_count("PRE_ROUTING"));
|
||||
EXPECT_EQ(0U, res->get_header_value_count("POST_ROUTING"));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -1246,8 +1250,8 @@ TEST(RoutingHandlerTest, PreRoutingHandler) {
|
||||
ASSERT_TRUE(res);
|
||||
EXPECT_EQ(404, res->status);
|
||||
EXPECT_EQ("Error", res->body);
|
||||
EXPECT_EQ(0, res->get_header_value_count("PRE_ROUTING"));
|
||||
EXPECT_EQ(0, res->get_header_value_count("POST_ROUTING"));
|
||||
EXPECT_EQ(0U, res->get_header_value_count("PRE_ROUTING"));
|
||||
EXPECT_EQ(0U, res->get_header_value_count("POST_ROUTING"));
|
||||
}
|
||||
|
||||
svr.stop();
|
||||
@@ -1306,31 +1310,31 @@ protected:
|
||||
.Get("/http_response_splitting",
|
||||
[&](const Request & /*req*/, Response &res) {
|
||||
res.set_header("a", "1\r\nSet-Cookie: a=1");
|
||||
EXPECT_EQ(0, res.headers.size());
|
||||
EXPECT_EQ(0U, res.headers.size());
|
||||
EXPECT_FALSE(res.has_header("a"));
|
||||
|
||||
res.set_header("a", "1\nSet-Cookie: a=1");
|
||||
EXPECT_EQ(0, res.headers.size());
|
||||
EXPECT_EQ(0U, res.headers.size());
|
||||
EXPECT_FALSE(res.has_header("a"));
|
||||
|
||||
res.set_header("a", "1\rSet-Cookie: a=1");
|
||||
EXPECT_EQ(0, res.headers.size());
|
||||
EXPECT_EQ(0U, res.headers.size());
|
||||
EXPECT_FALSE(res.has_header("a"));
|
||||
|
||||
res.set_header("a\r\nb", "0");
|
||||
EXPECT_EQ(0, res.headers.size());
|
||||
EXPECT_EQ(0U, res.headers.size());
|
||||
EXPECT_FALSE(res.has_header("a"));
|
||||
|
||||
res.set_header("a\rb", "0");
|
||||
EXPECT_EQ(0, res.headers.size());
|
||||
EXPECT_EQ(0U, res.headers.size());
|
||||
EXPECT_FALSE(res.has_header("a"));
|
||||
|
||||
res.set_header("a\nb", "0");
|
||||
EXPECT_EQ(0, res.headers.size());
|
||||
EXPECT_EQ(0U, res.headers.size());
|
||||
EXPECT_FALSE(res.has_header("a"));
|
||||
|
||||
res.set_redirect("1\r\nSet-Cookie: a=1");
|
||||
EXPECT_EQ(0, res.headers.size());
|
||||
EXPECT_EQ(0U, res.headers.size());
|
||||
EXPECT_FALSE(res.has_header("Location"));
|
||||
})
|
||||
.Get("/slow",
|
||||
@@ -1648,7 +1652,7 @@ protected:
|
||||
} else {
|
||||
std::string body;
|
||||
content_reader([&](const char *data, size_t data_length) {
|
||||
EXPECT_EQ(data_length, 7);
|
||||
EXPECT_EQ(7U, data_length);
|
||||
body.append(data, data_length);
|
||||
return true;
|
||||
});
|
||||
@@ -1696,7 +1700,7 @@ protected:
|
||||
})
|
||||
.Post("/binary",
|
||||
[&](const Request &req, Response &res) {
|
||||
EXPECT_EQ(4, req.body.size());
|
||||
EXPECT_EQ(4U, req.body.size());
|
||||
EXPECT_EQ("application/octet-stream",
|
||||
req.get_header_value("Content-Type"));
|
||||
EXPECT_EQ("4", req.get_header_value("Content-Length"));
|
||||
@@ -1704,7 +1708,7 @@ protected:
|
||||
})
|
||||
.Put("/binary",
|
||||
[&](const Request &req, Response &res) {
|
||||
EXPECT_EQ(4, req.body.size());
|
||||
EXPECT_EQ(4U, req.body.size());
|
||||
EXPECT_EQ("application/octet-stream",
|
||||
req.get_header_value("Content-Type"));
|
||||
EXPECT_EQ("4", req.get_header_value("Content-Length"));
|
||||
@@ -1712,7 +1716,7 @@ protected:
|
||||
})
|
||||
.Patch("/binary",
|
||||
[&](const Request &req, Response &res) {
|
||||
EXPECT_EQ(4, req.body.size());
|
||||
EXPECT_EQ(4U, req.body.size());
|
||||
EXPECT_EQ("application/octet-stream",
|
||||
req.get_header_value("Content-Type"));
|
||||
EXPECT_EQ("4", req.get_header_value("Content-Length"));
|
||||
@@ -1720,7 +1724,7 @@ protected:
|
||||
})
|
||||
.Delete("/binary",
|
||||
[&](const Request &req, Response &res) {
|
||||
EXPECT_EQ(4, req.body.size());
|
||||
EXPECT_EQ(4U, req.body.size());
|
||||
EXPECT_EQ("application/octet-stream",
|
||||
req.get_header_value("Content-Type"));
|
||||
EXPECT_EQ("4", req.get_header_value("Content-Length"));
|
||||
@@ -1800,7 +1804,7 @@ TEST_F(ServerTest, GetMethod200) {
|
||||
EXPECT_EQ(200, res->status);
|
||||
EXPECT_EQ("OK", res->reason);
|
||||
EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
|
||||
EXPECT_EQ(1, res->get_header_value_count("Content-Type"));
|
||||
EXPECT_EQ(1U, res->get_header_value_count("Content-Type"));
|
||||
EXPECT_EQ("Hello World!", res->body);
|
||||
}
|
||||
|
||||
@@ -1810,7 +1814,7 @@ TEST_F(ServerTest, GetMethod200withPercentEncoding) {
|
||||
EXPECT_EQ("HTTP/1.1", res->version);
|
||||
EXPECT_EQ(200, res->status);
|
||||
EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
|
||||
EXPECT_EQ(1, res->get_header_value_count("Content-Type"));
|
||||
EXPECT_EQ(1U, res->get_header_value_count("Content-Type"));
|
||||
EXPECT_EQ("Hello World!", res->body);
|
||||
}
|
||||
|
||||
@@ -2088,25 +2092,25 @@ TEST_F(ServerTest, Binary) {
|
||||
"application/octet-stream");
|
||||
ASSERT_TRUE(res);
|
||||
ASSERT_EQ(200, res->status);
|
||||
ASSERT_EQ(4, res->body.size());
|
||||
ASSERT_EQ(4U, res->body.size());
|
||||
|
||||
res = cli_.Put("/binary", binary.data(), binary.size(),
|
||||
"application/octet-stream");
|
||||
ASSERT_TRUE(res);
|
||||
ASSERT_EQ(200, res->status);
|
||||
ASSERT_EQ(4, res->body.size());
|
||||
ASSERT_EQ(4U, res->body.size());
|
||||
|
||||
res = cli_.Patch("/binary", binary.data(), binary.size(),
|
||||
"application/octet-stream");
|
||||
ASSERT_TRUE(res);
|
||||
ASSERT_EQ(200, res->status);
|
||||
ASSERT_EQ(4, res->body.size());
|
||||
ASSERT_EQ(4U, res->body.size());
|
||||
|
||||
res = cli_.Delete("/binary", binary.data(), binary.size(),
|
||||
"application/octet-stream");
|
||||
ASSERT_TRUE(res);
|
||||
ASSERT_EQ(200, res->status);
|
||||
ASSERT_EQ(4, res->body.size());
|
||||
ASSERT_EQ(4U, res->body.size());
|
||||
}
|
||||
|
||||
TEST_F(ServerTest, BinaryString) {
|
||||
@@ -2115,22 +2119,22 @@ TEST_F(ServerTest, BinaryString) {
|
||||
auto res = cli_.Post("/binary", binary, "application/octet-stream");
|
||||
ASSERT_TRUE(res);
|
||||
ASSERT_EQ(200, res->status);
|
||||
ASSERT_EQ(4, res->body.size());
|
||||
ASSERT_EQ(4U, res->body.size());
|
||||
|
||||
res = cli_.Put("/binary", binary, "application/octet-stream");
|
||||
ASSERT_TRUE(res);
|
||||
ASSERT_EQ(200, res->status);
|
||||
ASSERT_EQ(4, res->body.size());
|
||||
ASSERT_EQ(4U, res->body.size());
|
||||
|
||||
res = cli_.Patch("/binary", binary, "application/octet-stream");
|
||||
ASSERT_TRUE(res);
|
||||
ASSERT_EQ(200, res->status);
|
||||
ASSERT_EQ(4, res->body.size());
|
||||
ASSERT_EQ(4U, res->body.size());
|
||||
|
||||
res = cli_.Delete("/binary", binary, "application/octet-stream");
|
||||
ASSERT_TRUE(res);
|
||||
ASSERT_EQ(200, res->status);
|
||||
ASSERT_EQ(4, res->body.size());
|
||||
ASSERT_EQ(4U, res->body.size());
|
||||
}
|
||||
|
||||
TEST_F(ServerTest, EmptyRequest) {
|
||||
@@ -2446,7 +2450,7 @@ TEST_F(ServerTest, GetStreamedWithRangeMultipart) {
|
||||
EXPECT_EQ(206, res->status);
|
||||
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(269U, res->body.size());
|
||||
}
|
||||
|
||||
TEST_F(ServerTest, GetStreamedEndless) {
|
||||
@@ -2533,7 +2537,7 @@ TEST_F(ServerTest, GetWithRangeMultipart) {
|
||||
EXPECT_EQ(206, res->status);
|
||||
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(269U, res->body.size());
|
||||
}
|
||||
|
||||
TEST_F(ServerTest, GetWithRangeMultipartOffsetGreaterThanContent) {
|
||||
@@ -2864,6 +2868,54 @@ TEST(GzipDecompressor, ChunkedDecompression) {
|
||||
}
|
||||
ASSERT_EQ(data, decompressed_data);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
TEST(GzipDecompressor, LargeRandomData) {
|
||||
|
||||
// prepare large random data that is difficult to be compressed and is
|
||||
// expected to have large size even when compressed
|
||||
std::random_device seed_gen;
|
||||
std::mt19937 random(seed_gen());
|
||||
constexpr auto large_size_byte = 4294967296UL; // 4GiB
|
||||
constexpr auto data_size = large_size_byte + 134217728UL; // + 128MiB
|
||||
std::vector<std::uint32_t> data(data_size / sizeof(std::uint32_t));
|
||||
std::generate(data.begin(), data.end(), [&]() { return random(); });
|
||||
|
||||
// compress data over 4GiB
|
||||
std::string compressed_data;
|
||||
compressed_data.reserve(large_size_byte + 536870912UL); // + 512MiB reserved
|
||||
httplib::detail::gzip_compressor compressor;
|
||||
auto result = compressor.compress(reinterpret_cast<const char *>(data.data()),
|
||||
data.size() * sizeof(std::uint32_t), true,
|
||||
[&](const char *data, size_t size) {
|
||||
compressed_data.insert(
|
||||
compressed_data.size(), data, size);
|
||||
return true;
|
||||
});
|
||||
ASSERT_TRUE(result);
|
||||
|
||||
// FIXME: compressed data size is expected to be greater than 4GiB,
|
||||
// but there is no guarantee
|
||||
// ASSERT_TRUE(compressed_data.size() >= large_size_byte);
|
||||
|
||||
// decompress data over 4GiB
|
||||
std::string decompressed_data;
|
||||
decompressed_data.reserve(data_size);
|
||||
httplib::detail::gzip_decompressor decompressor;
|
||||
result = decompressor.decompress(
|
||||
compressed_data.data(), compressed_data.size(),
|
||||
[&](const char *data, size_t size) {
|
||||
decompressed_data.insert(decompressed_data.size(), data, size);
|
||||
return true;
|
||||
});
|
||||
ASSERT_TRUE(result);
|
||||
|
||||
// compare
|
||||
ASSERT_EQ(data_size, decompressed_data.size());
|
||||
ASSERT_TRUE(std::memcmp(data.data(), decompressed_data.data(), data_size) ==
|
||||
0);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CPPHTTPLIB_BROTLI_SUPPORT
|
||||
@@ -3124,7 +3176,7 @@ TEST_F(ServerTest, GzipWithContentReceiver) {
|
||||
std::string body;
|
||||
auto res = cli_.Get("/compress", headers,
|
||||
[&](const char *data, uint64_t data_length) {
|
||||
EXPECT_EQ(data_length, 100);
|
||||
EXPECT_EQ(100U, data_length);
|
||||
body.append(data, data_length);
|
||||
return true;
|
||||
});
|
||||
@@ -3150,14 +3202,14 @@ TEST_F(ServerTest, GzipWithoutDecompressing) {
|
||||
EXPECT_EQ("gzip", res->get_header_value("Content-Encoding"));
|
||||
EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
|
||||
EXPECT_EQ("33", res->get_header_value("Content-Length"));
|
||||
EXPECT_EQ(33, res->body.size());
|
||||
EXPECT_EQ(33U, res->body.size());
|
||||
EXPECT_EQ(200, res->status);
|
||||
}
|
||||
|
||||
TEST_F(ServerTest, GzipWithContentReceiverWithoutAcceptEncoding) {
|
||||
std::string body;
|
||||
auto res = cli_.Get("/compress", [&](const char *data, uint64_t data_length) {
|
||||
EXPECT_EQ(data_length, 100);
|
||||
EXPECT_EQ(100U, data_length);
|
||||
body.append(data, data_length);
|
||||
return true;
|
||||
});
|
||||
@@ -3193,7 +3245,7 @@ TEST_F(ServerTest, NoGzipWithContentReceiver) {
|
||||
std::string body;
|
||||
auto res = cli_.Get("/nocompress", headers,
|
||||
[&](const char *data, uint64_t data_length) {
|
||||
EXPECT_EQ(data_length, 100);
|
||||
EXPECT_EQ(100U, data_length);
|
||||
body.append(data, data_length);
|
||||
return true;
|
||||
});
|
||||
@@ -3289,14 +3341,14 @@ TEST(ServerRequestParsingTest, TrimWhitespaceFromHeaderValues) {
|
||||
// Only space and horizontal tab are whitespace. Make sure other whitespace-
|
||||
// like characters are not treated the same - use vertical tab and escape.
|
||||
const std::string req = "GET /validate-ws-in-headers HTTP/1.1\r\n"
|
||||
"foo: \t \v bar \e\t \r\n"
|
||||
"foo: \t \v bar \x1B\t \r\n"
|
||||
"Connection: close\r\n"
|
||||
"\r\n";
|
||||
|
||||
ASSERT_TRUE(send_request(5, req));
|
||||
svr.stop();
|
||||
t.join();
|
||||
EXPECT_EQ(header_value, "\v bar \e");
|
||||
EXPECT_EQ(header_value, "\v bar \x1B");
|
||||
}
|
||||
|
||||
// Sends a raw request and verifies that there isn't a crash or exception.
|
||||
@@ -3448,7 +3500,7 @@ TEST(ServerStopTest, StopServerWithChunkedTransmission) {
|
||||
res.set_chunked_content_provider("text/event-stream", [](size_t offset,
|
||||
DataSink &sink) {
|
||||
char buffer[27];
|
||||
auto size = static_cast<size_t>(sprintf(buffer, "data:%ld\n\n", offset));
|
||||
auto size = static_cast<size_t>(sprintf(buffer, "data:%zd\n\n", offset));
|
||||
auto ret = sink.write(buffer, size);
|
||||
EXPECT_TRUE(ret);
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
@@ -3705,19 +3757,19 @@ TEST(ErrorHandlerWithContentProviderTest, ErrorHandler) {
|
||||
TEST(GetWithParametersTest, GetWithParameters) {
|
||||
Server svr;
|
||||
|
||||
svr.Get("/", [&](const Request &req, Response &res) {
|
||||
svr.Get("/", [&](const Request &req, Response &) {
|
||||
EXPECT_EQ("world", req.get_param_value("hello"));
|
||||
EXPECT_EQ("world2", req.get_param_value("hello2"));
|
||||
EXPECT_EQ("world3", req.get_param_value("hello3"));
|
||||
});
|
||||
|
||||
svr.Get("/params", [&](const Request &req, Response &res) {
|
||||
svr.Get("/params", [&](const Request &req, Response &) {
|
||||
EXPECT_EQ("world", req.get_param_value("hello"));
|
||||
EXPECT_EQ("world2", req.get_param_value("hello2"));
|
||||
EXPECT_EQ("world3", req.get_param_value("hello3"));
|
||||
});
|
||||
|
||||
svr.Get(R"(/resources/([a-z0-9\\-]+))", [&](const Request& req, Response& res) {
|
||||
svr.Get(R"(/resources/([a-z0-9\\-]+))", [&](const Request& req, Response&) {
|
||||
EXPECT_EQ("resource-id", req.matches[1]);
|
||||
EXPECT_EQ("foo", req.get_param_value("param1"));
|
||||
EXPECT_EQ("bar", req.get_param_value("param2"));
|
||||
@@ -4411,7 +4463,7 @@ TEST(DecodeWithChunkedEncoding, BrotliEncoding) {
|
||||
|
||||
ASSERT_TRUE(res);
|
||||
EXPECT_EQ(200, res->status);
|
||||
EXPECT_EQ(287630, res->body.size());
|
||||
EXPECT_EQ(287630U, res->body.size());
|
||||
EXPECT_EQ("application/javascript; charset=utf-8",
|
||||
res->get_header_value("Content-Type"));
|
||||
}
|
||||
@@ -4452,4 +4504,38 @@ TEST(HttpsToHttpRedirectTest3, SimpleInterface) {
|
||||
ASSERT_TRUE(res);
|
||||
EXPECT_EQ(200, res->status);
|
||||
}
|
||||
|
||||
TEST(HttpToHttpsRedirectTest, CertFile) {
|
||||
Server svr;
|
||||
ASSERT_TRUE(svr.is_valid());
|
||||
svr.Get("/index", [&](const Request &, Response &res) {
|
||||
res.set_redirect("https://127.0.0.1:1235/index");
|
||||
svr.stop();
|
||||
});
|
||||
|
||||
SSLServer ssl_svr(SERVER_CERT2_FILE, SERVER_PRIVATE_KEY_FILE);
|
||||
ASSERT_TRUE(ssl_svr.is_valid());
|
||||
ssl_svr.Get("/index", [&](const Request &, Response &res) {
|
||||
res.set_content("test", "text/plain");
|
||||
ssl_svr.stop();
|
||||
});
|
||||
|
||||
|
||||
thread t = thread([&]() { ASSERT_TRUE(svr.listen("127.0.0.1", PORT)); });
|
||||
thread t2 = thread([&]() { ASSERT_TRUE(ssl_svr.listen("127.0.0.1", 1235)); });
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
|
||||
Client cli("127.0.0.1", PORT);
|
||||
cli.set_ca_cert_path(SERVER_CERT2_FILE);
|
||||
cli.enable_server_certificate_verification(true);
|
||||
cli.set_follow_location(true);
|
||||
cli.set_connection_timeout(30);
|
||||
|
||||
auto res = cli.Get("/index");
|
||||
ASSERT_TRUE(res);
|
||||
ASSERT_EQ(200, res->status);
|
||||
|
||||
t.join();
|
||||
t2.join();
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user