From 4b77a68f47f3c19109324c2ccb3a898a8334056f Mon Sep 17 00:00:00 2001 From: Hermann von Kleist Date: Mon, 3 Apr 2023 13:38:13 +0200 Subject: [PATCH 1/9] Add build and .cache to .gitignore build is commonly used with CMake (default build dir in VS code) .cache is used by clangd --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 29daf6a..b3f7949 100644 --- a/.gitignore +++ b/.gitignore @@ -7,8 +7,10 @@ cmake_install.cmake install_manifest.txt *.cmake #Additions to https://github.com/github/gitignore/blob/master/CMake.gitignore +build Testing compile_commands.json +.cache .usages_clang *.crt From b6783d40bea876601e163fbdc1cabc9823f477f3 Mon Sep 17 00:00:00 2001 From: Hermann von Kleist Date: Fri, 31 Mar 2023 17:18:48 +0200 Subject: [PATCH 2/9] CMake: find_package(asio) if available --- CMakeLists.txt | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fb8ca62..65a06e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,10 +24,20 @@ target_link_libraries(simple-web-server INTERFACE Threads::Threads) if(USE_STANDALONE_ASIO) target_compile_definitions(simple-web-server INTERFACE ASIO_STANDALONE) - find_path(ASIO_PATH asio.hpp) - if(NOT ASIO_PATH) - message(FATAL_ERROR "Standalone Asio not found") + # There is no canonical way to use Asio from CMake. + # In particular, Asio does not support CMake natively. + # However, Conan and Vcpkg do provide CMake support on their own. + # Prefer the CMake target and fall back to finding asio.hpp. + if(NOT TARGET asio::asio) + find_package(asio) + endif() + if(TARGET asio::asio) + target_link_libraries(simple-web-server INTERFACE asio::asio) else() + find_path(ASIO_PATH asio.hpp) + if(NOT ASIO_PATH) + message(FATAL_ERROR "Standalone Asio not found") + endif() target_include_directories(simple-web-server SYSTEM INTERFACE ${ASIO_PATH}) endif() else() From 27b41f5ee154cca0fce4fe2955dd886d04e3a4ed Mon Sep 17 00:00:00 2001 From: eidheim Date: Tue, 25 Apr 2023 13:03:22 +0200 Subject: [PATCH 3/9] Added -Wsign-conversion --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 65a06e9..78c94e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,7 +71,7 @@ endif() # If Simple-Web-Server is not a sub-project: if(CMAKE_SOURCE_DIR STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") if(NOT MSVC) - add_compile_options(-Wall -Wextra) + add_compile_options(-Wall -Wextra -Wsign-conversion) if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wthread-safety) endif() From 54eca45e5de484342f0bd07d16adfdd38819d471 Mon Sep 17 00:00:00 2001 From: brodo Date: Fri, 1 Sep 2023 11:13:39 +0200 Subject: [PATCH 4/9] Fix pipelined requests handling --- server_http.hpp | 63 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 19 deletions(-) diff --git a/server_http.hpp b/server_http.hpp index 1db0368..2e94be8 100644 --- a/server_http.hpp +++ b/server_http.hpp @@ -228,10 +228,16 @@ namespace SimpleWeb { friend class Session; asio::streambuf streambuf; + asio::streambuf content_streambuf; std::weak_ptr connection; std::string optimization = std::to_string(0); // TODO: figure out what goes wrong in gcc optimization without this line - Request(std::size_t max_request_streambuf_size, const std::shared_ptr &connection_) noexcept : streambuf(max_request_streambuf_size), connection(connection_), content(streambuf) {} + Request(std::size_t max_request_streambuf_size, const std::shared_ptr &connection_) noexcept + : streambuf(max_request_streambuf_size), content_streambuf(max_request_streambuf_size), connection(connection_), content(content_streambuf) {} + Request(std::size_t max_request_streambuf_size, const std::shared_ptr &connection_, asio::streambuf &&pending) noexcept + : streambuf(max_request_streambuf_size), content_streambuf(max_request_streambuf_size), connection(connection_), content(content_streambuf) { + std::ostream(&streambuf) << &pending; + } public: std::string method, path, query_string, http_version; @@ -348,6 +354,8 @@ namespace SimpleWeb { class Session { public: Session(std::size_t max_request_streambuf_size, std::shared_ptr connection_) noexcept : connection(std::move(connection_)), request(new Request(max_request_streambuf_size, connection)) {} + Session(std::size_t max_request_streambuf_size, std::shared_ptr connection_, asio::streambuf &&s) noexcept + : connection(std::move(connection_)), request(new Request(max_request_streambuf_size, connection, std::move(s))) {} std::shared_ptr connection; std::shared_ptr request; @@ -572,7 +580,8 @@ namespace SimpleWeb { // streambuf (maybe some bytes of the content) is appended to in the async_read-function below (for retrieving content). std::size_t num_additional_bytes = session->request->streambuf.size() - bytes_transferred; - if(!RequestMessage::parse(session->request->content, session->request->method, session->request->path, + std::istream istream(&session->request->streambuf); + if(!RequestMessage::parse(istream, session->request->method, session->request->path, session->request->query_string, session->request->http_version, session->request->header)) { if(this->on_error) this->on_error(session->request, make_error_code::make_error_code(errc::protocol_error)); @@ -598,8 +607,17 @@ namespace SimpleWeb { this->on_error(session->request, make_error_code::make_error_code(errc::message_size)); return; } + + if(num_additional_bytes > 0) { + auto content_bytes = std::min(content_length, (unsigned long long)num_additional_bytes); + auto &source = session->request->streambuf; + auto &target = session->request->content_streambuf; + target.commit(asio::buffer_copy(target.prepare(content_bytes), source.data(), content_bytes)); + source.consume(content_bytes); + } + if(content_length > num_additional_bytes) { - asio::async_read(*session->connection->socket, session->request->streambuf, asio::transfer_exactly(content_length - num_additional_bytes), [this, session](const error_code &ec, std::size_t /*bytes_transferred*/) { + asio::async_read(*session->connection->socket, session->request->content_streambuf, asio::transfer_exactly(content_length - num_additional_bytes), [this, session](const error_code &ec, std::size_t /*bytes_transferred*/) { auto lock = session->connection->handler_runner->continue_lock(); if(!lock) return; @@ -610,8 +628,9 @@ namespace SimpleWeb { this->on_error(session->request, ec); }); } - else + else { this->find_resource(session); + } } else if((header_it = session->request->header.find("Transfer-Encoding")) != session->request->header.end() && header_it->second == "chunked") { // Expect hex number to not exceed 16 bytes (64-bit number), but take into account previous additional read bytes @@ -654,12 +673,7 @@ namespace SimpleWeb { return; } - if(chunk_size == 0) { - this->find_resource(session); - return; - } - - if(chunk_size + session->request->streambuf.size() > session->request->streambuf.max_size()) { + if(chunk_size + session->request->content_streambuf.size() > session->request->content_streambuf.max_size()) { auto response = std::shared_ptr(new Response(session, this->config.timeout_content)); response->write(StatusCode::client_error_payload_too_large); if(this->on_error) @@ -667,19 +681,30 @@ namespace SimpleWeb { return; } + auto next_step = [this, chunk_size](const std::shared_ptr &session, const std::shared_ptr &chunk_size_streambuf) { + if(chunk_size == 0) { + // remaining bytes are the beginning of the next request + std::istream(chunk_size_streambuf.get()) >> &session->request->streambuf; + this->find_resource(session); + } + else { + this->read_chunked_transfer_encoded(session, chunk_size_streambuf); + } + }; + auto num_additional_bytes = chunk_size_streambuf->size() - bytes_transferred; auto bytes_to_move = std::min(chunk_size, num_additional_bytes); if(bytes_to_move > 0) { // Move leftover bytes auto &source = *chunk_size_streambuf; - auto &target = session->request->streambuf; + auto &target = session->request->content_streambuf; target.commit(asio::buffer_copy(target.prepare(bytes_to_move), source.data(), bytes_to_move)); source.consume(bytes_to_move); } if(chunk_size > num_additional_bytes) { - asio::async_read(*session->connection->socket, session->request->streambuf, asio::transfer_exactly(chunk_size - num_additional_bytes), [this, session, chunk_size_streambuf](const error_code &ec, size_t /*bytes_transferred*/) { + asio::async_read(*session->connection->socket, session->request->content_streambuf, asio::transfer_exactly(chunk_size - num_additional_bytes), [this, session, chunk_size_streambuf, next_step](const error_code &ec, size_t /*bytes_transferred*/) { auto lock = session->connection->handler_runner->continue_lock(); if(!lock) return; @@ -687,12 +712,12 @@ namespace SimpleWeb { if(!ec) { // Remove "\r\n" auto null_buffer = std::make_shared(2); - asio::async_read(*session->connection->socket, *null_buffer, asio::transfer_exactly(2), [this, session, chunk_size_streambuf, null_buffer](const error_code &ec, size_t /*bytes_transferred*/) { + asio::async_read(*session->connection->socket, *null_buffer, asio::transfer_exactly(2), [this, session, chunk_size_streambuf, null_buffer, next_step](const error_code &ec, size_t /*bytes_transferred*/) { auto lock = session->connection->handler_runner->continue_lock(); if(!lock) return; if(!ec) - read_chunked_transfer_encoded(session, chunk_size_streambuf); + next_step(session, chunk_size_streambuf); else this->on_error(session->request, ec); }); @@ -706,12 +731,12 @@ namespace SimpleWeb { if(2 + chunk_size - num_additional_bytes == 1) istream.get(); auto null_buffer = std::make_shared(2); - asio::async_read(*session->connection->socket, *null_buffer, asio::transfer_exactly(2 + chunk_size - num_additional_bytes), [this, session, chunk_size_streambuf, null_buffer](const error_code &ec, size_t /*bytes_transferred*/) { + asio::async_read(*session->connection->socket, *null_buffer, asio::transfer_exactly(2 + chunk_size - num_additional_bytes), [this, session, chunk_size_streambuf, null_buffer, next_step](const error_code &ec, size_t /*bytes_transferred*/) { auto lock = session->connection->handler_runner->continue_lock(); if(!lock) return; if(!ec) - read_chunked_transfer_encoded(session, chunk_size_streambuf); + next_step(session, chunk_size_streambuf); else this->on_error(session->request, ec); }); @@ -721,7 +746,7 @@ namespace SimpleWeb { istream.get(); istream.get(); - read_chunked_transfer_encoded(session, chunk_size_streambuf); + next_step(session, chunk_size_streambuf); } } else if(this->on_error) @@ -778,13 +803,13 @@ namespace SimpleWeb { if(case_insensitive_equal(it->second, "close")) return; else if(case_insensitive_equal(it->second, "keep-alive")) { - auto new_session = std::make_shared(this->config.max_request_streambuf_size, response->session->connection); + auto new_session = std::make_shared(this->config.max_request_streambuf_size, response->session->connection, std::move(response->session->request->streambuf)); this->read(new_session); return; } } if(response->session->request->http_version >= "1.1") { - auto new_session = std::make_shared(this->config.max_request_streambuf_size, response->session->connection); + auto new_session = std::make_shared(this->config.max_request_streambuf_size, response->session->connection, std::move(response->session->request->streambuf)); this->read(new_session); return; } From 4abe3491582b56c0b18fc35278aad33b2db29cdc Mon Sep 17 00:00:00 2001 From: eidheim Date: Tue, 6 Feb 2024 13:51:20 +0100 Subject: [PATCH 5/9] Slight improvement of !276 --- server_http.hpp | 58 ++++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/server_http.hpp b/server_http.hpp index 2e94be8..b7591c2 100644 --- a/server_http.hpp +++ b/server_http.hpp @@ -227,16 +227,15 @@ namespace SimpleWeb { friend class Server; friend class Session; - asio::streambuf streambuf; + std::unique_ptr streambuf; asio::streambuf content_streambuf; std::weak_ptr connection; std::string optimization = std::to_string(0); // TODO: figure out what goes wrong in gcc optimization without this line Request(std::size_t max_request_streambuf_size, const std::shared_ptr &connection_) noexcept - : streambuf(max_request_streambuf_size), content_streambuf(max_request_streambuf_size), connection(connection_), content(content_streambuf) {} - Request(std::size_t max_request_streambuf_size, const std::shared_ptr &connection_, asio::streambuf &&pending) noexcept - : streambuf(max_request_streambuf_size), content_streambuf(max_request_streambuf_size), connection(connection_), content(content_streambuf) { - std::ostream(&streambuf) << &pending; + : streambuf(new asio::streambuf(max_request_streambuf_size)), content_streambuf(max_request_streambuf_size), connection(connection_), content(content_streambuf) {} + Request(std::size_t max_request_streambuf_size, const std::shared_ptr &connection_, std::unique_ptr &&previous_streambuf) noexcept + : streambuf(std::move(previous_streambuf)), content_streambuf(max_request_streambuf_size), connection(connection_), content(content_streambuf) { } public: @@ -353,9 +352,10 @@ namespace SimpleWeb { class Session { public: - Session(std::size_t max_request_streambuf_size, std::shared_ptr connection_) noexcept : connection(std::move(connection_)), request(new Request(max_request_streambuf_size, connection)) {} - Session(std::size_t max_request_streambuf_size, std::shared_ptr connection_, asio::streambuf &&s) noexcept - : connection(std::move(connection_)), request(new Request(max_request_streambuf_size, connection, std::move(s))) {} + Session(std::size_t max_request_streambuf_size, std::shared_ptr connection_) noexcept + : connection(std::move(connection_)), request(new Request(max_request_streambuf_size, connection)) {} + Session(std::size_t max_request_streambuf_size, std::shared_ptr connection_, std::unique_ptr &&previous_streambuf) noexcept + : connection(std::move(connection_)), request(new Request(max_request_streambuf_size, connection, std::move(previous_streambuf))) {} std::shared_ptr connection; std::shared_ptr request; @@ -566,7 +566,7 @@ namespace SimpleWeb { void read(const std::shared_ptr &session) { session->connection->set_timeout(config.timeout_request); - asio::async_read_until(*session->connection->socket, session->request->streambuf, "\r\n\r\n", [this, session](const error_code &ec, std::size_t bytes_transferred) { + asio::async_read_until(*session->connection->socket, *session->request->streambuf, "\r\n\r\n", [this, session](const error_code &ec, std::size_t bytes_transferred) { auto lock = session->connection->handler_runner->continue_lock(); if(!lock) return; @@ -574,13 +574,13 @@ namespace SimpleWeb { if(!ec) { session->connection->set_timeout(this->config.timeout_content); - // request->streambuf.size() is not necessarily the same as bytes_transferred, from Boost-docs: + // request->streambuf->size() is not necessarily the same as bytes_transferred, from Boost-docs: // "After a successful async_read_until operation, the streambuf may contain additional data beyond the delimiter" // The chosen solution is to extract lines from the stream directly when parsing the header. What is left of the // streambuf (maybe some bytes of the content) is appended to in the async_read-function below (for retrieving content). - std::size_t num_additional_bytes = session->request->streambuf.size() - bytes_transferred; + std::size_t num_additional_bytes = session->request->streambuf->size() - bytes_transferred; - std::istream istream(&session->request->streambuf); + std::istream istream(session->request->streambuf.get()); if(!RequestMessage::parse(istream, session->request->method, session->request->path, session->request->query_string, session->request->http_version, session->request->header)) { if(this->on_error) @@ -600,7 +600,7 @@ namespace SimpleWeb { this->on_error(session->request, make_error_code::make_error_code(errc::protocol_error)); return; } - if(content_length > session->request->streambuf.max_size()) { + if(content_length > session->request->streambuf->max_size()) { auto response = std::shared_ptr(new Response(session, this->config.timeout_content)); response->write(StatusCode::client_error_payload_too_large); if(this->on_error) @@ -610,7 +610,7 @@ namespace SimpleWeb { if(num_additional_bytes > 0) { auto content_bytes = std::min(content_length, (unsigned long long)num_additional_bytes); - auto &source = session->request->streambuf; + auto &source = *session->request->streambuf; auto &target = session->request->content_streambuf; target.commit(asio::buffer_copy(target.prepare(content_bytes), source.data(), content_bytes)); source.consume(content_bytes); @@ -634,10 +634,10 @@ namespace SimpleWeb { } else if((header_it = session->request->header.find("Transfer-Encoding")) != session->request->header.end() && header_it->second == "chunked") { // Expect hex number to not exceed 16 bytes (64-bit number), but take into account previous additional read bytes - auto chunk_size_streambuf = std::make_shared(std::max(16 + 2, session->request->streambuf.size())); + auto chunk_size_streambuf = std::make_shared(std::max(16 + 2, session->request->streambuf->size())); // Move leftover bytes - auto &source = session->request->streambuf; + auto &source = *session->request->streambuf; auto &target = *chunk_size_streambuf; target.commit(asio::buffer_copy(target.prepare(source.size()), source.data())); source.consume(source.size()); @@ -681,15 +681,19 @@ namespace SimpleWeb { return; } - auto next_step = [this, chunk_size](const std::shared_ptr &session, const std::shared_ptr &chunk_size_streambuf) { + auto read_next = [this, chunk_size](const std::shared_ptr &session, const std::shared_ptr &chunk_size_streambuf) { if(chunk_size == 0) { - // remaining bytes are the beginning of the next request - std::istream(chunk_size_streambuf.get()) >> &session->request->streambuf; + if(chunk_size_streambuf->size() > 0) { + // Remaining bytes are the beginning of the next request + auto &source = *chunk_size_streambuf; + auto &target = *session->request->streambuf; + target.commit(asio::buffer_copy(target.prepare(chunk_size_streambuf->size()), source.data(), chunk_size_streambuf->size())); + source.consume(chunk_size_streambuf->size()); + } this->find_resource(session); } - else { + else this->read_chunked_transfer_encoded(session, chunk_size_streambuf); - } }; auto num_additional_bytes = chunk_size_streambuf->size() - bytes_transferred; @@ -704,7 +708,7 @@ namespace SimpleWeb { } if(chunk_size > num_additional_bytes) { - asio::async_read(*session->connection->socket, session->request->content_streambuf, asio::transfer_exactly(chunk_size - num_additional_bytes), [this, session, chunk_size_streambuf, next_step](const error_code &ec, size_t /*bytes_transferred*/) { + asio::async_read(*session->connection->socket, session->request->content_streambuf, asio::transfer_exactly(chunk_size - num_additional_bytes), [this, session, chunk_size_streambuf, read_next](const error_code &ec, size_t /*bytes_transferred*/) { auto lock = session->connection->handler_runner->continue_lock(); if(!lock) return; @@ -712,12 +716,12 @@ namespace SimpleWeb { if(!ec) { // Remove "\r\n" auto null_buffer = std::make_shared(2); - asio::async_read(*session->connection->socket, *null_buffer, asio::transfer_exactly(2), [this, session, chunk_size_streambuf, null_buffer, next_step](const error_code &ec, size_t /*bytes_transferred*/) { + asio::async_read(*session->connection->socket, *null_buffer, asio::transfer_exactly(2), [this, session, chunk_size_streambuf, null_buffer, read_next](const error_code &ec, size_t /*bytes_transferred*/) { auto lock = session->connection->handler_runner->continue_lock(); if(!lock) return; if(!ec) - next_step(session, chunk_size_streambuf); + read_next(session, chunk_size_streambuf); else this->on_error(session->request, ec); }); @@ -731,12 +735,12 @@ namespace SimpleWeb { if(2 + chunk_size - num_additional_bytes == 1) istream.get(); auto null_buffer = std::make_shared(2); - asio::async_read(*session->connection->socket, *null_buffer, asio::transfer_exactly(2 + chunk_size - num_additional_bytes), [this, session, chunk_size_streambuf, null_buffer, next_step](const error_code &ec, size_t /*bytes_transferred*/) { + asio::async_read(*session->connection->socket, *null_buffer, asio::transfer_exactly(2 + chunk_size - num_additional_bytes), [this, session, chunk_size_streambuf, null_buffer, read_next](const error_code &ec, size_t /*bytes_transferred*/) { auto lock = session->connection->handler_runner->continue_lock(); if(!lock) return; if(!ec) - next_step(session, chunk_size_streambuf); + read_next(session, chunk_size_streambuf); else this->on_error(session->request, ec); }); @@ -746,7 +750,7 @@ namespace SimpleWeb { istream.get(); istream.get(); - next_step(session, chunk_size_streambuf); + read_next(session, chunk_size_streambuf); } } else if(this->on_error) From 2469d730b1a0f944380166ad9049084054540c23 Mon Sep 17 00:00:00 2001 From: Gavin Smith Date: Thu, 3 Apr 2025 00:17:26 +0100 Subject: [PATCH 6/9] Made some member functions const where appropriate. --- client_http.hpp | 4 ++-- server_http.hpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client_http.hpp b/client_http.hpp index e12fcd2..87d8367 100644 --- a/client_http.hpp +++ b/client_http.hpp @@ -72,11 +72,11 @@ namespace SimpleWeb { friend class ClientBase; public: - std::size_t size() noexcept { + std::size_t size() const noexcept { return streambuf.size(); } /// Convenience function to return content as a string. - std::string string() noexcept { + std::string string() const noexcept { return std::string(asio::buffers_begin(streambuf.data()), asio::buffers_end(streambuf.data())); } diff --git a/server_http.hpp b/server_http.hpp index b7591c2..baace86 100644 --- a/server_http.hpp +++ b/server_http.hpp @@ -135,7 +135,7 @@ namespace SimpleWeb { } public: - std::size_t size() noexcept { + std::size_t size() const noexcept { return streambuf->size(); } @@ -209,11 +209,11 @@ namespace SimpleWeb { friend class ServerBase; public: - std::size_t size() noexcept { + std::size_t size() const noexcept { return streambuf.size(); } /// Convenience function to return content as std::string. - std::string string() noexcept { + std::string string() const noexcept { return std::string(asio::buffers_begin(streambuf.data()), asio::buffers_end(streambuf.data())); } From 26215025c8e21a5f844fd10654439fc23d68071c Mon Sep 17 00:00:00 2001 From: eidheim Date: Thu, 3 Apr 2025 10:58:13 +0200 Subject: [PATCH 7/9] Fixed deprecated calls --- asio_compatibility.hpp | 10 ++++++++-- client_http.hpp | 2 +- client_https.hpp | 6 +++++- crypto.hpp | 2 +- server_https.hpp | 2 +- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/asio_compatibility.hpp b/asio_compatibility.hpp index aa43451..e93c0cf 100644 --- a/asio_compatibility.hpp +++ b/asio_compatibility.hpp @@ -27,12 +27,18 @@ namespace SimpleWeb { #endif namespace SimpleWeb { -#if(defined(ASIO_STANDALONE) && ASIO_VERSION >= 101300) || BOOST_ASIO_VERSION >= 101300 +#if (defined(ASIO_STANDALONE) && ASIO_VERSION >= 103300) || BOOST_ASIO_VERSION >= 103300 + using const_buffer = asio::const_buffer; +#else + using const_buffer = asio::const_buffers_1; +#endif + +#if (defined(ASIO_STANDALONE) && ASIO_VERSION >= 101300) || BOOST_ASIO_VERSION >= 101300 using io_context = asio::io_context; using resolver_results = asio::ip::tcp::resolver::results_type; using async_connect_endpoint = asio::ip::tcp::endpoint; -#if(defined(ASIO_STANDALONE) && ASIO_VERSION >= 101800) || BOOST_ASIO_VERSION >= 101800 +#if (defined(ASIO_STANDALONE) && ASIO_VERSION >= 101800) || BOOST_ASIO_VERSION >= 101800 using strand = asio::strand; #else using strand = asio::strand; diff --git a/client_http.hpp b/client_http.hpp index e12fcd2..1228eb9 100644 --- a/client_http.hpp +++ b/client_http.hpp @@ -17,7 +17,7 @@ namespace SimpleWeb { public: /// Match condition for asio::read_until to match both standard and non-standard HTTP header endings. - std::pair, bool> operator()(asio::buffers_iterator begin, asio::buffers_iterator end) { + std::pair, bool> operator()(asio::buffers_iterator begin, asio::buffers_iterator end) { auto it = begin; for(; it != end; ++it) { if(*it == '\n') { diff --git a/client_https.hpp b/client_https.hpp index 86c042c..09d37ab 100644 --- a/client_https.hpp +++ b/client_https.hpp @@ -27,7 +27,7 @@ namespace SimpleWeb { Client(const std::string &server_port_path, bool verify_certificate = true, const std::string &certification_file = std::string(), const std::string &private_key_file = std::string(), const std::string &verify_file = std::string()) : ClientBase::ClientBase(server_port_path, 443), -#if(defined(ASIO_STANDALONE) && ASIO_VERSION >= 101300) || BOOST_ASIO_VERSION >= 101300 +#if (defined(ASIO_STANDALONE) && ASIO_VERSION >= 101300) || BOOST_ASIO_VERSION >= 101300 context(asio::ssl::context::tls_client) { // Disabling TLS 1.0 and 1.1 (see RFC 8996) context.set_options(asio::ssl::context::no_tlsv1); @@ -41,7 +41,11 @@ namespace SimpleWeb { } if(verify_certificate) +#if (defined(ASIO_STANDALONE) && ASIO_VERSION >= 103300) || BOOST_ASIO_VERSION >= 103300 + context.set_verify_callback(asio::ssl::host_name_verification(host)); +#else context.set_verify_callback(asio::ssl::rfc2818_verification(host)); +#endif if(verify_file.size() > 0) context.load_verify_file(verify_file); diff --git a/crypto.hpp b/crypto.hpp index 3629598..be9bfb9 100644 --- a/crypto.hpp +++ b/crypto.hpp @@ -70,7 +70,7 @@ namespace SimpleWeb { b64 = BIO_new(BIO_f_base64()); BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); // TODO: Remove in 2022 or later -#if(defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x1000214fL) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2080000fL) +#if (defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x1000214fL) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2080000fL) bio = BIO_new_mem_buf(const_cast(&base64[0]), static_cast(base64.size())); #else bio = BIO_new_mem_buf(&base64[0], static_cast(base64.size())); diff --git a/server_https.hpp b/server_https.hpp index 9b77fdc..7a02b68 100644 --- a/server_https.hpp +++ b/server_https.hpp @@ -29,7 +29,7 @@ namespace SimpleWeb { */ Server(const std::string &certification_file, const std::string &private_key_file, const std::string &verify_file = std::string()) : ServerBase::ServerBase(443), -#if(defined(ASIO_STANDALONE) && ASIO_VERSION >= 101300) || BOOST_ASIO_VERSION >= 101300 +#if (defined(ASIO_STANDALONE) && ASIO_VERSION >= 101300) || BOOST_ASIO_VERSION >= 101300 context(asio::ssl::context::tls_server) { // Disabling TLS 1.0 and 1.1 (see RFC 8996) context.set_options(asio::ssl::context::no_tlsv1); From 546895a93a29062bb178367b46c7afb72da9881e Mon Sep 17 00:00:00 2001 From: ReenigneArcher <2669457-ReenigneArcher@users.noreply.gitlab.com> Date: Sat, 13 Sep 2025 11:32:38 -0400 Subject: [PATCH 8/9] build(cmake): fix for boost 1.89 --- CMakeLists.txt | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 78c94e5..8c16916 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,8 +41,20 @@ if(USE_STANDALONE_ASIO) target_include_directories(simple-web-server SYSTEM INTERFACE ${ASIO_PATH}) endif() else() - find_package(Boost 1.53.0 COMPONENTS system REQUIRED) - target_link_libraries(simple-web-server INTERFACE Boost::boost Boost::system) + # In Boost 1.89.0+, system is header-only, so we try to find it but make it optional + find_package(Boost 1.53.0 COMPONENTS system) + if(NOT Boost_FOUND) + # Fallback: try without system component for newer Boost versions where it's header-only + find_package(Boost 1.53.0 REQUIRED) + endif() + + target_link_libraries(simple-web-server INTERFACE Boost::boost) + + # Only link Boost::system if the target exists (for older Boost < 1.89) + if(TARGET Boost::system) + target_link_libraries(simple-web-server INTERFACE Boost::system) + endif() + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) target_compile_definitions(simple-web-server INTERFACE USE_BOOST_REGEX) find_package(Boost 1.53.0 COMPONENTS regex REQUIRED) From 99c1f621ebd8d119c5d2dc3a88ecf255058acec0 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Wed, 11 Feb 2026 14:38:32 -0700 Subject: [PATCH 9/9] Add connection_shared() public accessor for SSL peer cert resolution --- server_http.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server_http.hpp b/server_http.hpp index baace86..50f7a86 100644 --- a/server_http.hpp +++ b/server_http.hpp @@ -297,6 +297,10 @@ namespace SimpleWeb { CaseInsensitiveMultimap parse_query_string() const noexcept { return SimpleWeb::QueryString::parse(query_string); } + + std::shared_ptr connection_shared() const noexcept { + return connection.lock(); + } }; protected: