Compare commits

...

18 Commits

Author SHA1 Message Date
yhirose f14accb7b6 Release v0.14.2 2023-12-04 22:31:12 -05:00
yhirose c5c704cb3b Fix #1724 2023-12-04 21:34:55 -05:00
Jean-Francois Simoneau 115a786581 Fix readability warnings (#1722)
* Fix readability warnings

Did not fix readbility-qualified-auto, will do a separate pull request

* Revert changes where meaning is lost

* Revert some style changes
2023-11-24 09:55:04 -05:00
Jean-Francois Simoneau 5ef4cfd263 Fix bugprone warnings (#1721) 2023-11-20 22:14:00 -05:00
Jean-Francois Simoneau 03fecb2f78 Fix modernize warnings (#1720) 2023-11-20 22:10:04 -05:00
Jean-Francois Simoneau 7fc8682a0a Fix performance-noexcept-move-constructor (#1715) 2023-11-20 13:13:59 -05:00
Jiwoo Park f1431311a4 Minor fixes on test cases (#1709)
* Fix data race

* Replace sleep_for() to wait_until_ready()
2023-11-11 21:28:50 -05:00
Jiwoo Park 1d14e051a5 Remove cryptui on Windows (#1710) 2023-11-11 21:26:57 -05:00
Jiwoo Park 97ae6733ed Run fuzz test in CTest (#1707) 2023-11-09 19:35:15 -05:00
Jiwoo Park 1d6b22b5f0 Fix C6001 (#1701) 2023-10-30 07:13:40 -04:00
yhirose 1a49076b5b Removed unnecessary exception 2023-10-29 19:36:40 -04:00
Jiwoo Park d0e4cb3f07 Include missing stdint.h on fuzz test (#1700)
* Include missing stdint.h

* Remove std:: from uint8_t
2023-10-29 19:26:06 -04:00
yhirose e2813d9d4d Code cleanup. (Removed unnecessary .c_str() calls) 2023-10-23 16:43:12 -04:00
Andrea Pappacoda 20a7f088ce build(meson): copy 1MB.txt test file (#1695)
Since tests are run in the build directory, the 1MB.txt file has to be
copied there.
2023-10-20 17:58:06 -04:00
yhirose f63ba7d013 Fix #1685 2023-10-03 09:59:27 -04:00
yhirose 0a629d7391 Release v0.14.1 2023-09-30 22:26:23 -04:00
PabloMK7 a609330e4c Add optional user defined header writer (#1683)
* Add optional user defined header writer

* Fix errors and add test
2023-09-30 22:13:14 -04:00
Jiwoo Park c029597a5a Update the remote address of www.httpwatch.com (#1664) 2023-09-13 10:33:33 -04:00
8 changed files with 258 additions and 191 deletions
-1
View File
@@ -219,7 +219,6 @@ target_link_libraries(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
# Needed for Windows libs on Mingw, as the pragma comment(lib, "xyz") aren't triggered.
$<$<PLATFORM_ID:Windows>:ws2_32>
$<$<PLATFORM_ID:Windows>:crypt32>
$<$<PLATFORM_ID:Windows>:cryptui>
# Needed for API from MacOS Security framework
"$<$<AND:$<PLATFORM_ID:Darwin>,$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>,$<BOOL:${HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN}>>:-framework CoreFoundation -framework Security>"
# Can't put multiple targets in a single generator expression or it bugs out.
+128 -93
View File
@@ -8,7 +8,7 @@
#ifndef CPPHTTPLIB_HTTPLIB_H
#define CPPHTTPLIB_HTTPLIB_H
#define CPPHTTPLIB_VERSION "0.14.0"
#define CPPHTTPLIB_VERSION "0.14.2"
/*
* Configuration
@@ -247,7 +247,6 @@ using socket_t = int;
#ifdef _MSC_VER
#pragma comment(lib, "crypt32.lib")
#pragma comment(lib, "cryptui.lib")
#endif
#elif defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN) && defined(__APPLE__)
#include <TargetConditionals.h>
@@ -331,7 +330,7 @@ struct scope_exit {
explicit scope_exit(std::function<void(void)> &&f)
: exit_function(std::move(f)), execute_on_destruction{true} {}
scope_exit(scope_exit &&rhs)
scope_exit(scope_exit &&rhs) noexcept
: exit_function(std::move(rhs.exit_function)),
execute_on_destruction{rhs.execute_on_destruction} {
rhs.release();
@@ -383,6 +382,7 @@ public:
DataSink &operator=(DataSink &&) = delete;
std::function<bool(const char *data, size_t data_len)> write;
std::function<bool()> is_writable;
std::function<void()> done;
std::function<void(const Headers &trailer)> done_with_trailer;
std::ostream os;
@@ -393,7 +393,7 @@ private:
explicit data_sink_streambuf(DataSink &sink) : sink_(sink) {}
protected:
std::streamsize xsputn(const char *s, std::streamsize n) {
std::streamsize xsputn(const char *s, std::streamsize n) override {
sink_.write(s, static_cast<size_t>(n));
return n;
}
@@ -737,6 +737,8 @@ private:
std::regex regex_;
};
ssize_t write_headers(Stream &strm, const Headers &headers);
} // namespace detail
class Server {
@@ -800,6 +802,8 @@ public:
Server &set_socket_options(SocketOptions socket_options);
Server &set_default_headers(Headers headers);
Server &
set_header_writer(std::function<ssize_t(Stream &, Headers &)> const &writer);
Server &set_keep_alive_max_count(size_t count);
Server &set_keep_alive_timeout(time_t sec);
@@ -865,15 +869,15 @@ private:
bool routing(Request &req, Response &res, Stream &strm);
bool handle_file_request(const Request &req, Response &res,
bool head = false);
bool dispatch_request(Request &req, Response &res, const Handlers &handlers);
bool
dispatch_request_for_content_reader(Request &req, Response &res,
ContentReader content_reader,
const HandlersForContentReader &handlers);
bool dispatch_request(Request &req, Response &res,
const Handlers &handlers) const;
bool dispatch_request_for_content_reader(
Request &req, Response &res, ContentReader content_reader,
const HandlersForContentReader &handlers) const;
bool parse_request_line(const char *s, Request &req);
bool parse_request_line(const char *s, Request &req) const;
void apply_ranges(const Request &req, Response &res,
std::string &content_type, std::string &boundary);
std::string &content_type, std::string &boundary) const;
bool write_response(Stream &strm, bool close_connection, const Request &req,
Response &res);
bool write_response_with_content(Stream &strm, bool close_connection,
@@ -893,7 +897,7 @@ private:
bool read_content_core(Stream &strm, Request &req, Response &res,
ContentReceiver receiver,
MultipartContentHeader multipart_header,
ContentReceiver multipart_receiver);
ContentReceiver multipart_receiver) const;
virtual bool process_and_close_socket(socket_t sock);
@@ -934,6 +938,8 @@ private:
SocketOptions socket_options_ = default_socket_options;
Headers default_headers_;
std::function<ssize_t(Stream &, Headers &)> header_writer_ =
detail::write_headers;
};
enum class Error {
@@ -957,7 +963,7 @@ enum class Error {
SSLPeerCouldBeClosed_,
};
std::string to_string(const Error error);
std::string to_string(Error error);
std::ostream &operator<<(std::ostream &os, const Error &obj);
@@ -1164,6 +1170,9 @@ public:
void set_default_headers(Headers headers);
void
set_header_writer(std::function<ssize_t(Stream &, Headers &)> const &writer);
void set_address_family(int family);
void set_tcp_nodelay(bool on);
void set_socket_options(SocketOptions socket_options);
@@ -1212,7 +1221,7 @@ public:
void set_ca_cert_path(const std::string &ca_cert_file_path,
const std::string &ca_cert_dir_path = std::string());
void set_ca_cert_store(X509_STORE *ca_cert_store);
X509_STORE *create_ca_cert_store(const char *ca_cert, std::size_t size);
X509_STORE *create_ca_cert_store(const char *ca_cert, std::size_t size) const;
#endif
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
@@ -1241,14 +1250,14 @@ protected:
// Also, shutdown_ssl and close_socket should also NOT be called concurrently
// with a DIFFERENT thread sending requests using that socket.
virtual void shutdown_ssl(Socket &socket, bool shutdown_gracefully);
void shutdown_socket(Socket &socket);
void shutdown_socket(Socket &socket) const;
void close_socket(Socket &socket);
bool process_request(Stream &strm, Request &req, Response &res,
bool close_connection, Error &error);
bool write_content_with_provider(Stream &strm, const Request &req,
Error &error);
Error &error) const;
void copy_settings(const ClientImpl &rhs);
@@ -1273,6 +1282,10 @@ protected:
// Default headers
Headers default_headers_;
// Header writer
std::function<ssize_t(Stream &, Headers &)> header_writer_ =
detail::write_headers;
// Settings
std::string client_cert_path_;
std::string client_key_path_;
@@ -1335,7 +1348,8 @@ private:
Result send_(Request &&req);
socket_t create_client_socket(Error &error) const;
bool read_response_line(Stream &strm, const Request &req, Response &res);
bool read_response_line(Stream &strm, const Request &req,
Response &res) const;
bool write_request(Stream &strm, Request &req, bool close_connection,
Error &error);
bool redirect(Request &req, Response &res, Error &error);
@@ -1354,7 +1368,7 @@ private:
const std::string &content_type);
ContentProviderWithoutLength get_multipart_content_provider(
const std::string &boundary, const MultipartFormDataItems &items,
const MultipartFormDataProviderItems &provider_items);
const MultipartFormDataProviderItems &provider_items) const;
std::string adjust_host_string(const std::string &host) const;
@@ -1539,6 +1553,9 @@ public:
void set_default_headers(Headers headers);
void
set_header_writer(std::function<ssize_t(Stream &, Headers &)> const &writer);
void set_address_family(int family);
void set_tcp_nodelay(bool on);
void set_socket_options(SocketOptions socket_options);
@@ -1664,7 +1681,7 @@ public:
private:
bool create_and_connect_socket(Socket &socket, Error &error) override;
void shutdown_ssl(Socket &socket, bool shutdown_gracefully) override;
void shutdown_ssl_impl(Socket &socket, bool shutdown_socket);
void shutdown_ssl_impl(Socket &socket, bool shutdown_gracefully);
bool process_socket(const Socket &socket,
std::function<bool(Stream &strm)> callback) override;
@@ -2050,7 +2067,7 @@ public:
class nocompressor : public compressor {
public:
virtual ~nocompressor() = default;
~nocompressor() override = default;
bool compress(const char *data, size_t data_length, bool /*last*/,
Callback callback) override;
@@ -2060,7 +2077,7 @@ public:
class gzip_compressor : public compressor {
public:
gzip_compressor();
~gzip_compressor();
~gzip_compressor() override;
bool compress(const char *data, size_t data_length, bool last,
Callback callback) override;
@@ -2073,7 +2090,7 @@ private:
class gzip_decompressor : public decompressor {
public:
gzip_decompressor();
~gzip_decompressor();
~gzip_decompressor() override;
bool is_valid() const override;
@@ -2212,7 +2229,7 @@ inline std::string from_i_to_hex(size_t n) {
inline size_t to_utf8(int code, char *buff) {
if (code < 0x0080) {
buff[0] = (code & 0x7F);
buff[0] = static_cast<char>(code & 0x7F);
return 1;
} else if (code < 0x0800) {
buff[0] = static_cast<char>(0xC0 | ((code >> 6) & 0x1F));
@@ -2547,7 +2564,7 @@ inline mmap::mmap(const char *path)
#endif
,
size_(0), addr_(nullptr) {
if (!open(path)) { std::runtime_error(""); }
open(path);
}
inline mmap::~mmap() { close(); }
@@ -2820,7 +2837,7 @@ private:
size_t read_buff_off_ = 0;
size_t read_buff_content_size_ = 0;
static const size_t read_buff_size_ = 1024 * 4;
static const size_t read_buff_size_ = 1024l * 4;
};
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
@@ -2949,7 +2966,7 @@ socket_t create_socket(const std::string &host, const std::string &ip, int port,
#ifndef _WIN32
if (hints.ai_family == AF_UNIX) {
const auto addrlen = host.length();
if (addrlen > sizeof(sockaddr_un::sun_path)) return INVALID_SOCKET;
if (addrlen > sizeof(sockaddr_un::sun_path)) { return INVALID_SOCKET; }
auto sock = socket(hints.ai_family, hints.ai_socktype, hints.ai_protocol);
if (sock != INVALID_SOCKET) {
@@ -3153,7 +3170,7 @@ inline socket_t create_client_socket(
#ifdef USE_IF2IP
auto ip_from_if = if2ip(address_family, intf);
if (ip_from_if.empty()) { ip_from_if = intf; }
if (!bind_ip_address(sock2, ip_from_if.c_str())) {
if (!bind_ip_address(sock2, ip_from_if)) {
error = Error::BindIPAddress;
return false;
}
@@ -3310,7 +3327,7 @@ find_content_type(const std::string &path,
auto ext = file_extension(path);
auto it = user_data.find(ext);
if (it != user_data.end()) { return it->second.c_str(); }
if (it != user_data.end()) { return it->second; }
using udl::operator""_t;
@@ -3521,7 +3538,7 @@ inline bool gzip_decompressor::decompress(const char *data, size_t data_length,
}
}
if (ret != Z_OK && ret != Z_STREAM_END) return false;
if (ret != Z_OK && ret != Z_STREAM_END) { return false; }
} while (data_length > 0);
@@ -3789,7 +3806,7 @@ inline bool read_content_chunked(Stream &strm, T &x,
if (!line_reader.getline()) { return false; }
if (strcmp(line_reader.ptr(), "\r\n")) { return false; }
if (strcmp(line_reader.ptr(), "\r\n") != 0) { return false; }
if (!line_reader.getline()) { return false; }
}
@@ -3799,7 +3816,7 @@ inline bool read_content_chunked(Stream &strm, T &x,
// Trailer
if (!line_reader.getline()) { return false; }
while (strcmp(line_reader.ptr(), "\r\n")) {
while (strcmp(line_reader.ptr(), "\r\n") != 0) {
if (line_reader.size() > CPPHTTPLIB_HEADER_MAX_LENGTH) { return false; }
// Exclude line terminator
@@ -3943,6 +3960,8 @@ inline bool write_content(Stream &strm, const ContentProvider &content_provider,
return ok;
};
data_sink.is_writable = [&]() -> bool { return strm.is_writable(); };
while (offset < end_offset && !is_shutting_down()) {
if (!strm.is_writable()) {
error = Error::Write;
@@ -3987,6 +4006,8 @@ write_content_without_length(Stream &strm,
return ok;
};
data_sink.is_writable = [&]() -> bool { return strm.is_writable(); };
data_sink.done = [&](void) { data_available = false; };
while (data_available && !is_shutting_down()) {
@@ -4037,6 +4058,8 @@ write_content_chunked(Stream &strm, const ContentProvider &content_provider,
return ok;
};
data_sink.is_writable = [&]() -> bool { return strm.is_writable(); };
auto done_with_trailer = [&](const Headers *trailer) {
if (!ok) { return; }
@@ -4134,7 +4157,7 @@ inline bool redirect(T &cli, Request &req, Response &res,
req = new_req;
res = new_res;
if (res.location.empty()) res.location = location;
if (res.location.empty()) { res.location = location; }
}
return ret;
}
@@ -4221,7 +4244,7 @@ inline bool parse_range_header(const std::string &s, Ranges &ranges) try {
auto len = static_cast<size_t>(m.length(1));
auto all_valid_ranges = true;
split(&s[pos], &s[pos + len], ',', [&](const char *b, const char *e) {
if (!all_valid_ranges) return;
if (!all_valid_ranges) { return; }
static auto re_another_range = std::regex(R"(\s*(\d*)-(\d*))");
std::cmatch cm;
if (std::regex_match(b, e, cm, re_another_range)) {
@@ -4572,7 +4595,7 @@ serialize_multipart_formdata(const MultipartFormDataItems &items,
body += item.content + serialize_multipart_formdata_item_end();
}
if (finish) body += serialize_multipart_formdata_finish(boundary);
if (finish) { body += serialize_multipart_formdata_finish(boundary); }
return body;
}
@@ -5280,7 +5303,7 @@ inline SocketStream::SocketStream(socket_t sock, time_t read_timeout_sec,
write_timeout_sec_(write_timeout_sec),
write_timeout_usec_(write_timeout_usec), read_buff_(read_buff_size_, 0) {}
inline SocketStream::~SocketStream() {}
inline SocketStream::~SocketStream() = default;
inline bool SocketStream::is_readable() const {
return select_read(sock_, read_timeout_sec_, read_timeout_usec_) > 0;
@@ -5494,7 +5517,7 @@ inline Server::Server()
#endif
}
inline Server::~Server() {}
inline Server::~Server() = default;
inline std::unique_ptr<detail::MatcherBase>
Server::make_matcher(const std::string &pattern) {
@@ -5506,66 +5529,60 @@ Server::make_matcher(const std::string &pattern) {
}
inline Server &Server::Get(const std::string &pattern, Handler handler) {
get_handlers_.push_back(
std::make_pair(make_matcher(pattern), std::move(handler)));
get_handlers_.emplace_back(make_matcher(pattern), std::move(handler));
return *this;
}
inline Server &Server::Post(const std::string &pattern, Handler handler) {
post_handlers_.push_back(
std::make_pair(make_matcher(pattern), std::move(handler)));
post_handlers_.emplace_back(make_matcher(pattern), std::move(handler));
return *this;
}
inline Server &Server::Post(const std::string &pattern,
HandlerWithContentReader handler) {
post_handlers_for_content_reader_.push_back(
std::make_pair(make_matcher(pattern), std::move(handler)));
post_handlers_for_content_reader_.emplace_back(make_matcher(pattern),
std::move(handler));
return *this;
}
inline Server &Server::Put(const std::string &pattern, Handler handler) {
put_handlers_.push_back(
std::make_pair(make_matcher(pattern), std::move(handler)));
put_handlers_.emplace_back(make_matcher(pattern), std::move(handler));
return *this;
}
inline Server &Server::Put(const std::string &pattern,
HandlerWithContentReader handler) {
put_handlers_for_content_reader_.push_back(
std::make_pair(make_matcher(pattern), std::move(handler)));
put_handlers_for_content_reader_.emplace_back(make_matcher(pattern),
std::move(handler));
return *this;
}
inline Server &Server::Patch(const std::string &pattern, Handler handler) {
patch_handlers_.push_back(
std::make_pair(make_matcher(pattern), std::move(handler)));
patch_handlers_.emplace_back(make_matcher(pattern), std::move(handler));
return *this;
}
inline Server &Server::Patch(const std::string &pattern,
HandlerWithContentReader handler) {
patch_handlers_for_content_reader_.push_back(
std::make_pair(make_matcher(pattern), std::move(handler)));
patch_handlers_for_content_reader_.emplace_back(make_matcher(pattern),
std::move(handler));
return *this;
}
inline Server &Server::Delete(const std::string &pattern, Handler handler) {
delete_handlers_.push_back(
std::make_pair(make_matcher(pattern), std::move(handler)));
delete_handlers_.emplace_back(make_matcher(pattern), std::move(handler));
return *this;
}
inline Server &Server::Delete(const std::string &pattern,
HandlerWithContentReader handler) {
delete_handlers_for_content_reader_.push_back(
std::make_pair(make_matcher(pattern), std::move(handler)));
delete_handlers_for_content_reader_.emplace_back(make_matcher(pattern),
std::move(handler));
return *this;
}
inline Server &Server::Options(const std::string &pattern, Handler handler) {
options_handlers_.push_back(
std::make_pair(make_matcher(pattern), std::move(handler)));
options_handlers_.emplace_back(make_matcher(pattern), std::move(handler));
return *this;
}
@@ -5672,6 +5689,12 @@ inline Server &Server::set_default_headers(Headers headers) {
return *this;
}
inline Server &Server::set_header_writer(
std::function<ssize_t(Stream &, Headers &)> const &writer) {
header_writer_ = writer;
return *this;
}
inline Server &Server::set_keep_alive_max_count(size_t count) {
keep_alive_max_count_ = count;
return *this;
@@ -5707,8 +5730,7 @@ inline Server &Server::set_payload_max_length(size_t length) {
inline bool Server::bind_to_port(const std::string &host, int port,
int socket_flags) {
if (bind_internal(host, port, socket_flags) < 0) return false;
return true;
return bind_internal(host, port, socket_flags) >= 0;
}
inline int Server::bind_to_any_port(const std::string &host, int socket_flags) {
return bind_internal(host, 0, socket_flags);
@@ -5742,7 +5764,7 @@ inline void Server::stop() {
}
}
inline bool Server::parse_request_line(const char *s, Request &req) {
inline bool Server::parse_request_line(const char *s, Request &req) const {
auto len = strlen(s);
if (len < 2 || s[len - 2] != '\r' || s[len - 1] != '\n') { return false; }
len -= 2;
@@ -5866,7 +5888,7 @@ inline bool Server::write_response_core(Stream &strm, bool close_connection,
return false;
}
if (!detail::write_headers(bstrm, res.headers)) { return false; }
if (!header_writer_(bstrm, res.headers)) { return false; }
// Flush buffer
auto &data = bstrm.get_buffer();
@@ -5993,10 +6015,11 @@ inline bool Server::read_content_with_content_receiver(
std::move(multipart_receiver));
}
inline bool Server::read_content_core(Stream &strm, Request &req, Response &res,
ContentReceiver receiver,
MultipartContentHeader multipart_header,
ContentReceiver multipart_receiver) {
inline bool
Server::read_content_core(Stream &strm, Request &req, Response &res,
ContentReceiver receiver,
MultipartContentHeader multipart_header,
ContentReceiver multipart_receiver) const {
detail::MultipartFormDataParser multipart_form_data_parser;
ContentReceiverWithProgress out;
@@ -6060,7 +6083,7 @@ inline bool Server::handle_file_request(const Request &req, Response &res,
if (detail::is_file(path)) {
for (const auto &kv : entry.headers) {
res.set_header(kv.first.c_str(), kv.second);
res.set_header(kv.first, kv.second);
}
auto mm = std::make_shared<detail::mmap>(path.c_str());
@@ -6287,7 +6310,7 @@ inline bool Server::routing(Request &req, Response &res, Stream &strm) {
}
inline bool Server::dispatch_request(Request &req, Response &res,
const Handlers &handlers) {
const Handlers &handlers) const {
for (const auto &x : handlers) {
const auto &matcher = x.first;
const auto &handler = x.second;
@@ -6302,7 +6325,7 @@ inline bool Server::dispatch_request(Request &req, Response &res,
inline void Server::apply_ranges(const Request &req, Response &res,
std::string &content_type,
std::string &boundary) {
std::string &boundary) const {
if (req.ranges.size() > 1) {
boundary = detail::make_multipart_data_boundary();
@@ -6414,7 +6437,7 @@ inline void Server::apply_ranges(const Request &req, Response &res,
inline bool Server::dispatch_request_for_content_reader(
Request &req, Response &res, ContentReader content_reader,
const HandlersForContentReader &handlers) {
const HandlersForContentReader &handlers) const {
for (const auto &x : handlers) {
const auto &matcher = x.first;
const auto &handler = x.second;
@@ -6656,7 +6679,7 @@ inline socket_t ClientImpl::create_client_socket(Error &error) const {
// Check is custom IP specified for host_
std::string ip;
auto it = addr_map_.find(host_);
if (it != addr_map_.end()) ip = it->second;
if (it != addr_map_.end()) { ip = it->second; }
return detail::create_client_socket(
host_, ip, port_, address_family_, tcp_nodelay_, socket_options_,
@@ -6681,7 +6704,7 @@ inline void ClientImpl::shutdown_ssl(Socket & /*socket*/,
socket_requests_are_from_thread_ == std::this_thread::get_id());
}
inline void ClientImpl::shutdown_socket(Socket &socket) {
inline void ClientImpl::shutdown_socket(Socket &socket) const {
if (socket.sock == INVALID_SOCKET) { return; }
detail::shutdown_socket(socket.sock);
}
@@ -6706,7 +6729,7 @@ inline void ClientImpl::close_socket(Socket &socket) {
}
inline bool ClientImpl::read_response_line(Stream &strm, const Request &req,
Response &res) {
Response &res) const {
std::array<char, 2048> buf{};
detail::stream_line_reader line_reader(strm, buf.data(), buf.size());
@@ -6970,7 +6993,7 @@ inline bool ClientImpl::redirect(Request &req, Response &res, Error &error) {
} else {
if (next_scheme == "https") {
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
SSLClient cli(next_host.c_str(), next_port);
SSLClient cli(next_host, next_port);
cli.copy_settings(*this);
if (ca_cert_store_) { cli.set_ca_cert_store(ca_cert_store_); }
return detail::redirect(cli, req, res, path, location, error);
@@ -6978,7 +7001,7 @@ inline bool ClientImpl::redirect(Request &req, Response &res, Error &error) {
return false;
#endif
} else {
ClientImpl cli(next_host.c_str(), next_port);
ClientImpl cli(next_host, next_port);
cli.copy_settings(*this);
return detail::redirect(cli, req, res, path, location, error);
}
@@ -6987,7 +7010,7 @@ inline bool ClientImpl::redirect(Request &req, Response &res, Error &error) {
inline bool ClientImpl::write_content_with_provider(Stream &strm,
const Request &req,
Error &error) {
Error &error) const {
auto is_shutting_down = []() { return false; };
if (req.is_chunked_content_provider_) {
@@ -7105,7 +7128,7 @@ inline bool ClientImpl::write_request(Stream &strm, Request &req,
const auto &path = url_encode_ ? detail::encode_url(req.path) : req.path;
bstrm.write_format("%s %s HTTP/1.1\r\n", req.method.c_str(), path.c_str());
detail::write_headers(bstrm, req.headers);
header_writer_(bstrm, req.headers);
// Flush buffer
auto &data = bstrm.get_buffer();
@@ -7313,13 +7336,14 @@ inline bool ClientImpl::process_request(Stream &strm, Request &req,
inline ContentProviderWithoutLength ClientImpl::get_multipart_content_provider(
const std::string &boundary, const MultipartFormDataItems &items,
const MultipartFormDataProviderItems &provider_items) {
size_t cur_item = 0, cur_start = 0;
const MultipartFormDataProviderItems &provider_items) const {
size_t cur_item = 0;
size_t cur_start = 0;
// cur_item and cur_start are copied to within the std::function and maintain
// state between successive calls
return [&, cur_item, cur_start](size_t offset,
DataSink &sink) mutable -> bool {
if (!offset && items.size()) {
if (!offset && !items.empty()) {
sink.os << detail::serialize_multipart_formdata(items, boundary, false);
return true;
} else if (cur_item < provider_items.size()) {
@@ -7336,8 +7360,9 @@ inline ContentProviderWithoutLength ClientImpl::get_multipart_content_provider(
cur_sink.write = sink.write;
cur_sink.done = [&]() { has_data = false; };
if (!provider_items[cur_item].provider(offset - cur_start, cur_sink))
if (!provider_items[cur_item].provider(offset - cur_start, cur_sink)) {
return false;
}
if (!has_data) {
sink.os << detail::serialize_multipart_formdata_item_end();
@@ -7456,7 +7481,7 @@ inline Result ClientImpl::Get(const std::string &path, const Params &params,
if (params.empty()) { return Get(path, headers); }
std::string path_with_query = append_query_params(path, params);
return Get(path_with_query.c_str(), headers, progress);
return Get(path_with_query, headers, progress);
}
inline Result ClientImpl::Get(const std::string &path, const Params &params,
@@ -7476,8 +7501,8 @@ inline Result ClientImpl::Get(const std::string &path, const Params &params,
}
std::string path_with_query = append_query_params(path, params);
return Get(path_with_query.c_str(), headers, response_handler,
content_receiver, progress);
return Get(path_with_query, headers, response_handler, content_receiver,
progress);
}
inline Result ClientImpl::Head(const std::string &path) {
@@ -7579,7 +7604,7 @@ inline Result ClientImpl::Post(const std::string &path, const Headers &headers,
const auto &content_type =
detail::serialize_multipart_formdata_get_content_type(boundary);
const auto &body = detail::serialize_multipart_formdata(items, boundary);
return Post(path, headers, body, content_type.c_str());
return Post(path, headers, body, content_type);
}
inline Result ClientImpl::Post(const std::string &path, const Headers &headers,
@@ -7592,7 +7617,7 @@ inline Result ClientImpl::Post(const std::string &path, const Headers &headers,
const auto &content_type =
detail::serialize_multipart_formdata_get_content_type(boundary);
const auto &body = detail::serialize_multipart_formdata(items, boundary);
return Post(path, headers, body, content_type.c_str());
return Post(path, headers, body, content_type);
}
inline Result
@@ -7916,6 +7941,11 @@ inline void ClientImpl::set_default_headers(Headers headers) {
default_headers_ = std::move(headers);
}
inline void ClientImpl::set_header_writer(
std::function<ssize_t(Stream &, Headers &)> const &writer) {
header_writer_ = writer;
}
inline void ClientImpl::set_address_family(int family) {
address_family_ = family;
}
@@ -7969,9 +7999,9 @@ inline void ClientImpl::set_ca_cert_store(X509_STORE *ca_cert_store) {
}
inline X509_STORE *ClientImpl::create_ca_cert_store(const char *ca_cert,
std::size_t size) {
std::size_t size) const {
auto mem = BIO_new_mem_buf(ca_cert, static_cast<int>(size));
if (!mem) return nullptr;
if (!mem) { return nullptr; }
auto inf = PEM_X509_INFO_read_bio(mem, nullptr, nullptr, nullptr);
if (!inf) {
@@ -8121,7 +8151,7 @@ inline SSLSocketStream::SSLSocketStream(socket_t sock, SSL *ssl,
SSL_clear_mode(ssl, SSL_MODE_AUTO_RETRY);
}
inline SSLSocketStream::~SSLSocketStream() {}
inline SSLSocketStream::~SSLSocketStream() = default;
inline bool SSLSocketStream::is_readable() const {
return detail::select_read(sock_, read_timeout_sec_, read_timeout_usec_) > 0;
@@ -8337,7 +8367,7 @@ inline SSLClient::SSLClient(const std::string &host, int port,
detail::split(&host_[0], &host_[host_.size()], '.',
[&](const char *b, const char *e) {
host_components_.emplace_back(std::string(b, e));
host_components_.emplace_back(b, e);
});
if (!client_cert_path.empty() && !client_key_path.empty()) {
@@ -8358,7 +8388,7 @@ inline SSLClient::SSLClient(const std::string &host, int port,
detail::split(&host_[0], &host_[host_.size()], '.',
[&](const char *b, const char *e) {
host_components_.emplace_back(std::string(b, e));
host_components_.emplace_back(b, e);
});
if (client_cert != nullptr && client_key != nullptr) {
@@ -8632,8 +8662,8 @@ SSLClient::verify_host_with_subject_alt_name(X509 *server_cert) const {
auto type = GEN_DNS;
struct in6_addr addr6;
struct in_addr addr;
struct in6_addr addr6 {};
struct in_addr addr {};
size_t addr_len = 0;
#ifndef __MINGW32__
@@ -8708,7 +8738,7 @@ inline bool SSLClient::check_host_name(const char *pattern,
std::vector<std::string> pattern_components;
detail::split(&pattern[0], &pattern[pattern_len], '.',
[&](const char *b, const char *e) {
pattern_components.emplace_back(std::string(b, e));
pattern_components.emplace_back(b, e);
});
if (host_components_.size() != pattern_components.size()) { return false; }
@@ -8787,7 +8817,7 @@ inline Client::Client(const std::string &host, int port,
: cli_(detail::make_unique<ClientImpl>(host, port, client_cert_path,
client_key_path)) {}
inline Client::~Client() {}
inline Client::~Client() = default;
inline bool Client::is_valid() const {
return cli_ != nullptr && cli_->is_valid();
@@ -9110,6 +9140,11 @@ inline void Client::set_default_headers(Headers headers) {
cli_->set_default_headers(std::move(headers));
}
inline void Client::set_header_writer(
std::function<ssize_t(Stream &, Headers &)> const &writer) {
cli_->set_header_writer(writer);
}
inline void Client::set_address_family(int family) {
cli_->set_address_family(family);
}
+2
View File
@@ -102,3 +102,5 @@ if(HTTPLIB_IS_USING_OPENSSL)
COMMAND_ERROR_IS_FATAL ANY
)
endif()
add_subdirectory(fuzzing)
+10
View File
@@ -0,0 +1,10 @@
file(GLOB HTTPLIB_CORPUS corpus/*)
add_executable(httplib-test-fuzz
server_fuzzer.cc
standalone_fuzz_target_runner.cpp
)
target_link_libraries(httplib-test-fuzz PRIVATE httplib)
add_test(
NAME httplib-test-fuzz
COMMAND httplib-test-fuzz ${HTTPLIB_CORPUS}
)
+2 -1
View File
@@ -1,5 +1,6 @@
#include <cstdint>
#include <httplib.h>
#include <memory>
class FuzzedStream : public httplib::Stream {
public:
@@ -5,9 +5,9 @@
// on the test corpus or on a single file,
// e.g. the one that comes from a bug report.
#include <cassert>
#include <iostream>
#include <cstdint>
#include <fstream>
#include <iostream>
#include <vector>
// Forward declare the "fuzz target" interface.
@@ -21,7 +21,7 @@ int main(int argc, char **argv) {
std::ifstream in(argv[i]);
in.seekg(0, in.end);
size_t length = static_cast<size_t>(in.tellg());
in.seekg (0, in.beg);
in.seekg(0, in.beg);
std::cout << "Reading " << length << " bytes from " << argv[i] << std::endl;
// Allocate exactly length bytes so that we reliably catch buffer overflows.
std::vector<char> bytes(length);
+112 -93
View File
@@ -442,7 +442,7 @@ TEST(HostnameToIPConversionTest, HTTPWatch_Online) {
auto host = "www.httpwatch.com";
auto ip = hosted_at(host);
EXPECT_EQ("191.236.16.12", ip);
EXPECT_EQ("23.96.13.243", ip);
std::vector<std::string> addrs;
hosted_at(host, addrs);
@@ -1088,12 +1088,8 @@ TEST(RedirectToDifferentPort, Redirect) {
ASSERT_FALSE(svr1.is_running());
});
while (!svr1.is_running() || !svr2.is_running()) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
// Give GET time to get a few messages.
std::this_thread::sleep_for(std::chrono::seconds(1));
svr1.wait_until_ready();
svr2.wait_until_ready();
Client cli("localhost", svr2_port);
cli.set_follow_location(true);
@@ -1125,9 +1121,6 @@ TEST(RedirectFromPageWithContent, Redirect) {
svr.wait_until_ready();
// Give GET time to get a few messages.
std::this_thread::sleep_for(std::chrono::seconds(1));
{
Client cli("localhost", PORT);
cli.set_follow_location(true);
@@ -1193,9 +1186,6 @@ TEST(RedirectFromPageWithContentIP6, Redirect) {
ASSERT_LT(milliseconds, 5000U);
}
// Give GET time to get a few messages.
std::this_thread::sleep_for(std::chrono::seconds(1));
{
Client cli("http://[::1]:1234");
cli.set_follow_location(true);
@@ -1246,8 +1236,7 @@ TEST(PathUrlEncodeTest, PathUrlEncode) {
ASSERT_FALSE(svr.is_running());
});
// Give GET time to get a few messages.
std::this_thread::sleep_for(std::chrono::seconds(1));
svr.wait_until_ready();
{
Client cli(HOST, PORT);
@@ -1277,8 +1266,7 @@ TEST(BindServerTest, DISABLED_BindDualStack) {
ASSERT_FALSE(svr.is_running());
});
// Give GET time to get a few messages.
std::this_thread::sleep_for(std::chrono::seconds(1));
svr.wait_until_ready();
{
Client cli("127.0.0.1", PORT);
@@ -1349,8 +1337,7 @@ TEST(ErrorHandlerTest, ContentLength) {
ASSERT_FALSE(svr.is_running());
});
// Give GET time to get a few messages.
std::this_thread::sleep_for(std::chrono::seconds(1));
svr.wait_until_ready();
{
Client cli(HOST, PORT);
@@ -1391,8 +1378,7 @@ TEST(ExceptionHandlerTest, ContentLength) {
ASSERT_FALSE(svr.is_running());
});
// Give GET time to get a few messages.
std::this_thread::sleep_for(std::chrono::seconds(1));
svr.wait_until_ready();
for (size_t i = 0; i < 10; i++) {
Client cli(HOST, PORT);
@@ -1432,8 +1418,7 @@ TEST(NoContentTest, ContentLength) {
ASSERT_FALSE(svr.is_running());
});
// Give GET time to get a few messages.
std::this_thread::sleep_for(std::chrono::seconds(1));
svr.wait_until_ready();
{
Client cli(HOST, PORT);
@@ -1483,8 +1468,7 @@ TEST(RoutingHandlerTest, PreRoutingHandler) {
ASSERT_FALSE(svr.is_running());
});
// Give GET time to get a few messages.
std::this_thread::sleep_for(std::chrono::seconds(1));
svr.wait_until_ready();
{
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
@@ -1552,8 +1536,7 @@ TEST(InvalidFormatTest, StatusCode) {
ASSERT_FALSE(svr.is_running());
});
// Give GET time to get a few messages.
std::this_thread::sleep_for(std::chrono::seconds(1));
svr.wait_until_ready();
{
Client cli(HOST, PORT);
@@ -1577,7 +1560,7 @@ TEST(URLFragmentTest, WithFragment) {
ASSERT_FALSE(svr.is_running());
});
std::this_thread::sleep_for(std::chrono::seconds(1));
svr.wait_until_ready();
{
Client cli(HOST, PORT);
@@ -1592,6 +1575,46 @@ TEST(URLFragmentTest, WithFragment) {
}
}
TEST(HeaderWriter, SetHeaderWriter) {
Server svr;
svr.set_header_writer([](Stream &strm, Headers &hdrs) {
hdrs.emplace("CustomServerHeader", "CustomServerValue");
return detail::write_headers(strm, hdrs);
});
svr.Get("/hi", [](const Request &req, Response &res) {
auto it = req.headers.find("CustomClientHeader");
EXPECT_TRUE(it != req.headers.end());
EXPECT_EQ(it->second, "CustomClientValue");
res.set_content("Hello World!\n", "text/plain");
});
auto thread = std::thread([&]() { svr.listen(HOST, PORT); });
auto se = detail::scope_exit([&] {
svr.stop();
thread.join();
ASSERT_FALSE(svr.is_running());
});
svr.wait_until_ready();
{
Client cli(HOST, PORT);
cli.set_header_writer([](Stream &strm, Headers &hdrs) {
hdrs.emplace("CustomClientHeader", "CustomClientValue");
return detail::write_headers(strm, hdrs);
});
auto res = cli.Get("/hi");
EXPECT_TRUE(res);
EXPECT_EQ(200, res->status);
auto it = res->headers.find("CustomServerHeader");
EXPECT_TRUE(it != res->headers.end());
EXPECT_EQ(it->second, "CustomServerValue");
}
}
class ServerTest : public ::testing::Test {
protected:
ServerTest()
@@ -2165,9 +2188,7 @@ protected:
t_ = thread([&]() { ASSERT_TRUE(svr_.listen(HOST, PORT)); });
while (!svr_.is_running()) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
svr_.wait_until_ready();
}
virtual void TearDown() {
@@ -4182,9 +4203,6 @@ TEST(MountTest, Unmount) {
svr.wait_until_ready();
// Give GET time to get a few messages.
std::this_thread::sleep_for(std::chrono::seconds(1));
Client cli("localhost", PORT);
svr.set_mount_point("/mount2", "./www2");
@@ -4235,9 +4253,6 @@ TEST(ExceptionTest, ThrowExceptionInHandler) {
svr.wait_until_ready();
// Give GET time to get a few messages.
std::this_thread::sleep_for(std::chrono::seconds(1));
Client cli("localhost", PORT);
{
@@ -4279,9 +4294,6 @@ TEST(KeepAliveTest, ReadTimeout) {
svr.wait_until_ready();
// Give GET time to get a few messages.
std::this_thread::sleep_for(std::chrono::seconds(1));
Client cli("localhost", PORT);
cli.set_keep_alive(true);
cli.set_read_timeout(std::chrono::seconds(1));
@@ -4311,7 +4323,7 @@ TEST(KeepAliveTest, Issue1041) {
ASSERT_FALSE(svr.is_running());
});
std::this_thread::sleep_for(std::chrono::milliseconds(200));
svr.wait_until_ready();
Client cli(HOST, PORT);
cli.set_keep_alive(true);
@@ -4344,7 +4356,7 @@ TEST(KeepAliveTest, SSLClientReconnection) {
ASSERT_FALSE(svr.is_running());
});
std::this_thread::sleep_for(std::chrono::milliseconds(200));
svr.wait_until_ready();
SSLClient cli(HOST, PORT);
cli.enable_server_certificate_verification(false);
@@ -4407,9 +4419,6 @@ TEST(ClientProblemDetectionTest, ContentProvider) {
svr.wait_until_ready();
// Give GET time to get a few messages.
std::this_thread::sleep_for(std::chrono::seconds(1));
Client cli("localhost", PORT);
{
@@ -4447,9 +4456,6 @@ TEST(ErrorHandlerWithContentProviderTest, ErrorHandler) {
svr.wait_until_ready();
// Give GET time to get a few messages.
std::this_thread::sleep_for(std::chrono::seconds(1));
Client cli("localhost", PORT);
auto res = cli.Get("/");
@@ -4458,6 +4464,43 @@ TEST(ErrorHandlerWithContentProviderTest, ErrorHandler) {
EXPECT_EQ("helloworld", res->body);
}
TEST(LongPollingTest, ClientCloseDetection) {
Server svr;
svr.Get("/events", [&](const Request & /*req*/, Response &res) {
res.set_chunked_content_provider(
"text/plain", [](std::size_t const, DataSink &sink) -> bool {
EXPECT_TRUE(sink.is_writable()); // the socket is alive
sink.os << "hello";
auto count = 10;
while (count > 0 && sink.is_writable()) {
this_thread::sleep_for(chrono::milliseconds(10));
}
EXPECT_FALSE(sink.is_writable()); // the socket is closed
return true;
});
});
auto listen_thread = std::thread([&svr]() { svr.listen("localhost", PORT); });
auto se = detail::scope_exit([&] {
svr.stop();
listen_thread.join();
ASSERT_FALSE(svr.is_running());
});
svr.wait_until_ready();
Client cli("localhost", PORT);
auto res = cli.Get("/events", [&](const char *data, size_t data_length) {
EXPECT_EQ("hello", string(data, data_length));
return false; // close the socket immediately.
});
ASSERT_FALSE(res);
}
TEST(GetWithParametersTest, GetWithParameters) {
Server svr;
@@ -4493,7 +4536,6 @@ TEST(GetWithParametersTest, GetWithParameters) {
});
svr.wait_until_ready();
std::this_thread::sleep_for(std::chrono::seconds(1));
{
Client cli(HOST, PORT);
@@ -4552,7 +4594,6 @@ TEST(GetWithParametersTest, GetWithParameters2) {
});
svr.wait_until_ready();
std::this_thread::sleep_for(std::chrono::seconds(1));
Client cli("localhost", PORT);
@@ -4620,7 +4661,6 @@ TEST(ServerDefaultHeadersTest, DefaultHeaders) {
});
svr.wait_until_ready();
std::this_thread::sleep_for(std::chrono::seconds(1));
Client cli("localhost", PORT);
@@ -4655,9 +4695,6 @@ TEST(KeepAliveTest, ReadTimeoutSSL) {
svr.wait_until_ready();
// Give GET time to get a few messages.
std::this_thread::sleep_for(std::chrono::seconds(1));
SSLClient cli("localhost", PORT);
cli.enable_server_certificate_verification(false);
cli.set_keep_alive(true);
@@ -4696,9 +4733,7 @@ protected:
t_ = thread(
[&]() { ASSERT_TRUE(svr_.listen(std::string(), PORT, AI_PASSIVE)); });
while (!svr_.is_running()) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
svr_.wait_until_ready();
}
virtual void TearDown() {
@@ -4735,9 +4770,7 @@ protected:
ASSERT_TRUE(svr_.listen_after_bind());
});
while (!svr_.is_running()) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
svr_.wait_until_ready();
}
virtual void TearDown() {
@@ -4778,9 +4811,7 @@ protected:
t_ = thread([&]() { ASSERT_TRUE(svr_.listen(HOST, PORT)); });
while (!svr_.is_running()) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
svr_.wait_until_ready();
}
virtual void TearDown() {
@@ -4897,7 +4928,7 @@ TEST(SSLClientTest, ServerCertificateVerification4) {
ASSERT_FALSE(svr.is_running());
});
std::this_thread::sleep_for(std::chrono::milliseconds(1));
svr.wait_until_ready();
SSLClient cli("127.0.0.1", PORT);
cli.set_ca_cert_path(SERVER_CERT2_FILE);
@@ -5013,7 +5044,7 @@ TEST(SSLClientServerTest, ClientCertPresent) {
ASSERT_FALSE(svr.is_running());
});
std::this_thread::sleep_for(std::chrono::milliseconds(1));
svr.wait_until_ready();
SSLClient cli(HOST, PORT, CLIENT_CERT_FILE, CLIENT_PRIVATE_KEY_FILE);
cli.enable_server_certificate_verification(false);
@@ -5088,7 +5119,7 @@ TEST(SSLClientServerTest, MemoryClientCertPresent) {
ASSERT_FALSE(svr.is_running());
});
std::this_thread::sleep_for(std::chrono::milliseconds(1));
svr.wait_until_ready();
SSLClient cli(HOST, PORT, client_cert, client_private_key);
cli.enable_server_certificate_verification(false);
@@ -5119,7 +5150,7 @@ TEST(SSLClientServerTest, ClientCertMissing) {
ASSERT_FALSE(svr.is_running());
});
std::this_thread::sleep_for(std::chrono::milliseconds(1));
svr.wait_until_ready();
SSLClient cli(HOST, PORT);
auto res = cli.Get("/test");
@@ -5143,7 +5174,7 @@ TEST(SSLClientServerTest, TrustDirOptional) {
ASSERT_FALSE(svr.is_running());
});
std::this_thread::sleep_for(std::chrono::milliseconds(1));
svr.wait_until_ready();
SSLClient cli(HOST, PORT, CLIENT_CERT_FILE, CLIENT_PRIVATE_KEY_FILE);
cli.enable_server_certificate_verification(false);
@@ -5164,12 +5195,12 @@ TEST(SSLClientServerTest, SSLConnectTimeout) {
client_ca_cert_dir_path),
stop_(false) {}
bool stop_;
std::atomic_bool stop_;
private:
bool process_and_close_socket(socket_t /*sock*/) override {
// Don't create SSL context
while (!stop_) {
while (!stop_.load()) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
return true;
@@ -5191,7 +5222,7 @@ TEST(SSLClientServerTest, SSLConnectTimeout) {
ASSERT_FALSE(svr.is_running());
});
std::this_thread::sleep_for(std::chrono::milliseconds(1));
svr.wait_until_ready();
SSLClient cli(HOST, PORT, CLIENT_CERT_FILE, CLIENT_PRIVATE_KEY_FILE);
cli.enable_server_certificate_verification(false);
@@ -5263,7 +5294,7 @@ TEST(SSLClientServerTest, CustomizeServerSSLCtx) {
ASSERT_FALSE(svr.is_running());
});
std::this_thread::sleep_for(std::chrono::milliseconds(1));
svr.wait_until_ready();
SSLClient cli(HOST, PORT, CLIENT_CERT_FILE, CLIENT_PRIVATE_KEY_FILE);
cli.enable_server_certificate_verification(false);
@@ -5399,9 +5430,10 @@ TEST(ServerLargeContentTest, DISABLED_SendLargeContent) {
ASSERT_TRUE(content);
Server svr;
svr.Get("/foo", [=](const httplib::Request &req, httplib::Response &resp) {
resp.set_content(content, content_size, "application/octet-stream");
});
svr.Get("/foo",
[=](const httplib::Request & /*req*/, httplib::Response &res) {
res.set_content(content, content_size, "application/octet-stream");
});
auto listen_thread = std::thread([&svr]() { svr.listen(HOST, PORT); });
auto se = detail::scope_exit([&] {
@@ -5413,9 +5445,6 @@ TEST(ServerLargeContentTest, DISABLED_SendLargeContent) {
svr.wait_until_ready();
// Give GET time to get a few messages.
std::this_thread::sleep_for(std::chrono::seconds(1));
Client cli(HOST, PORT);
auto res = cli.Get("/foo");
ASSERT_TRUE(res);
@@ -5550,7 +5579,8 @@ TEST(HttpToHttpsRedirectTest, CertFile) {
ASSERT_FALSE(svr.is_running());
});
std::this_thread::sleep_for(std::chrono::milliseconds(1));
svr.wait_until_ready();
ssl_svr.wait_until_ready();
Client cli("127.0.0.1", PORT);
cli.set_ca_cert_path(SERVER_CERT2_FILE);
@@ -5606,7 +5636,6 @@ TEST(MultipartFormDataTest, LargeData) {
});
svr.wait_until_ready();
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::string data(1024 * 1024 * 2, '.');
@@ -5754,7 +5783,6 @@ TEST(MultipartFormDataTest, DataProviderItems) {
});
svr.wait_until_ready();
std::this_thread::sleep_for(std::chrono::seconds(1));
{
Client cli("https://localhost:8080");
@@ -5956,7 +5984,6 @@ TEST(MultipartFormDataTest, PostCustomBoundary) {
});
svr.wait_until_ready();
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::string data(1024 * 1024 * 2, '.');
@@ -5978,9 +6005,6 @@ TEST(MultipartFormDataTest, PostCustomBoundary) {
}
TEST(MultipartFormDataTest, PostInvalidBoundaryChars) {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::string data(1024 * 1024 * 2, '&');
std::stringstream buffer;
buffer << data;
@@ -6043,7 +6067,6 @@ TEST(MultipartFormDataTest, PutFormData) {
});
svr.wait_until_ready();
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::string data(1024 * 1024 * 2, '&');
@@ -6108,7 +6131,6 @@ TEST(MultipartFormDataTest, PutFormDataCustomBoundary) {
});
svr.wait_until_ready();
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::string data(1024 * 1024 * 2, '&');
@@ -6130,9 +6152,6 @@ TEST(MultipartFormDataTest, PutFormDataCustomBoundary) {
}
TEST(MultipartFormDataTest, PutInvalidBoundaryChars) {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::string data(1024 * 1024 * 2, '&');
std::stringstream buffer;
buffer << data;
@@ -6202,7 +6221,7 @@ TEST(MultipartFormDataTest, AlternateFilename) {
"\r\n"
"text default\r\n"
"----------\r\n"
"Content-Disposition: form-data; filename*=\"UTF-8''\%41.txt\"; "
"Content-Disposition: form-data; filename*=\"UTF-8''%41.txt\"; "
"filename=\"a.txt\"; name=\"file1\"\r\n"
"Content-Type: text/plain\r\n"
"\r\n"
@@ -6461,7 +6480,7 @@ TEST(RedirectTest, RedirectToUrlWithQueryParameters) {
ASSERT_FALSE(svr.is_running());
});
std::this_thread::sleep_for(std::chrono::seconds(1));
svr.wait_until_ready();
{
Client cli(HOST, PORT);
@@ -6507,7 +6526,7 @@ TEST(VulnerabilityTest, CRLFInjection) {
ASSERT_FALSE(svr.is_running());
});
std::this_thread::sleep_for(std::chrono::seconds(1));
svr.wait_until_ready();
{
Client cli(HOST, PORT);
+1
View File
@@ -5,3 +5,4 @@
configure_file(input: 'index.html', output: 'index.html', copy: true)
configure_file(input: 'test.abcde', output: 'test.abcde', copy: true)
configure_file(input: 'test.html', output: 'test.html', copy: true)
configure_file(input: '1MB.txt', output: '1MB.txt', copy: true)