Fix
publish / publish (push) Successful in 26m13s

This commit is contained in:
khodowany
2026-10-06 04:12:27 -05:00
parent 7a86cedeb3
commit e4125d4c4b
3 changed files with 57 additions and 14 deletions
+15 -10
View File
@@ -549,16 +549,8 @@ auto call_http_endpoint(ligo::http::endpoint endpoint, std::shared_ptr<ligo::htt
co_return co_await read_http_response(stream, options.timeout, options.max_body_size);
}
http_server_state::http_server_state(boost::asio::any_io_executor executor, ligo::http::endpoint endpoint, ligo::service_router router, ligo::http::server_options options)
: ligo::detail::stream_listener{std::move(executor), std::move(router)}, endpoint{std::move(endpoint)}, options{options} {}
}
ligo::http::client::client(ligo::http::endpoint endpoint, ligo::http::client_options options)
: endpoint_{std::move(endpoint)}, options_{options} {}
auto ligo::http::client::call(ligo::http::request const &request) const -> boost::asio::awaitable<std::expected<boost::json::value, modulus::error>> {
auto response = co_await exchange(request);
auto unwrap_http_response(boost::asio::awaitable<std::expected<ligo::http::response, modulus::error>> operation) -> boost::asio::awaitable<std::expected<boost::json::value, modulus::error>> {
auto response = co_await std::move(operation);
if (!response) {
co_return std::unexpected(response.error());
}
@@ -570,6 +562,19 @@ auto ligo::http::client::call(ligo::http::request const &request) const -> boost
co_return ligo::detail::unwrap_response_envelope(std::move(body), "HTTP");
}
http_server_state::http_server_state(boost::asio::any_io_executor executor, ligo::http::endpoint endpoint, ligo::service_router router, ligo::http::server_options options)
: ligo::detail::stream_listener{std::move(executor), std::move(router)}, endpoint{std::move(endpoint)}, options{options} {}
}
ligo::http::client::client(ligo::http::endpoint endpoint, ligo::http::client_options options)
: endpoint_{std::move(endpoint)}, options_{options} {}
auto ligo::http::client::call(ligo::http::request const &request) const -> boost::asio::awaitable<std::expected<boost::json::value, modulus::error>> {
// Capture inputs now: the client and request may expire before the coroutine runs.
return unwrap_http_response(exchange(request));
}
auto ligo::http::client::exchange(ligo::http::request const &request) const -> boost::asio::awaitable<std::expected<ligo::http::response, modulus::error>> {
return call_http_endpoint(endpoint_, std::make_shared<ligo::http::request const>(request), options_);
}
+1 -1
View File
@@ -14,7 +14,7 @@ target_compile_definitions(ligo_test PRIVATE
$<$<CONFIG:Debug>:LIGO_EXPECT_DEBUG_ASSERTS>
$<$<NOT:$<CONFIG:Debug>>:LIGO_EXPECT_NDEBUG>
)
add_test(NAME ligo COMMAND ligo_test)
add_test(NAME ligo COMMAND ligo_test --log_level=test_suite)
set_tests_properties(ligo PROPERTIES TIMEOUT 60)
add_custom_target(check
COMMAND ${CMAKE_CTEST_COMMAND}
+41 -3
View File
@@ -1,6 +1,7 @@
#include <atomic>
#include <chrono>
#include <cstdint>
#include <exception>
#include <fstream>
#include <future>
#include <memory>
@@ -2257,6 +2258,38 @@ BOOST_AUTO_TEST_CASE(ligo_udp_multithreaded_io_context_round_trip_succeeds) {
BOOST_CHECK(message->payload.as_object().at("ok").as_bool());
}
BOOST_AUTO_TEST_CASE(ligo_http_client_operations_capture_inputs_before_await) {
auto io = boost::asio::io_context{};
auto client = ligo::http::client{{"127.0.0.1", 1}};
auto request = ligo::http::request{.target = ""};
auto call = client.call(request);
auto exchange = client.exchange(request);
client = ligo::http::client{{"127.0.0.1", 0}};
request.target = "/";
auto called = boost::asio::co_spawn(io, std::move(call), boost::asio::use_future);
auto exchanged = boost::asio::co_spawn(io, std::move(exchange), boost::asio::use_future);
io.run();
auto call_result = called.get();
BOOST_REQUIRE(!call_result);
BOOST_CHECK_EQUAL(call_result.error().code(), ligo::detail::error_invalid_argument);
BOOST_CHECK_EQUAL(call_result.error().message(), "HTTP target must not be empty");
auto exchange_result = exchanged.get();
BOOST_REQUIRE(!exchange_result);
BOOST_CHECK_EQUAL(exchange_result.error().code(), ligo::detail::error_invalid_argument);
BOOST_CHECK_EQUAL(exchange_result.error().message(), "HTTP target must not be empty");
}
BOOST_AUTO_TEST_CASE(ligo_http_client_call_outlives_client_and_request) {
auto io = boost::asio::io_context{};
// Both the helper's client and this temporary request expire before io.run().
auto future = boost::asio::co_spawn(io, http_client_call("127.0.0.1", 1, {.target = ""}), boost::asio::use_future);
io.run();
auto result = future.get();
BOOST_REQUIRE(!result);
BOOST_CHECK_EQUAL(result.error().code(), ligo::detail::error_invalid_argument);
BOOST_CHECK_EQUAL(result.error().message(), "HTTP target must not be empty");
}
BOOST_AUTO_TEST_CASE(ligo_response_metadata_is_preserved_by_router) {
auto io = boost::asio::io_context{};
auto router = ligo::service_router{};
@@ -2314,9 +2347,14 @@ BOOST_AUTO_TEST_CASE(ligo_http_raw_exchange_headers_query_and_status) {
auto duplicate = co_await client.exchange(duplicate_request);
BOOST_REQUIRE(duplicate);
BOOST_CHECK_EQUAL(duplicate->status, 400);
server.stop();
};
auto future = boost::asio::co_spawn(io, exercise(), boost::asio::use_future);
auto failure = std::exception_ptr{};
boost::asio::co_spawn(io, exercise(), [&](std::exception_ptr error) {
failure = error;
server.stop();
});
io.run();
future.get();
if (failure) {
std::rethrow_exception(failure);
}
}