Skip to content

Commit 17710f1

Browse files
committed
fix: handle changing the body in the callback
1 parent ab97f30 commit 17710f1

3 files changed

Lines changed: 69 additions & 2 deletions

File tree

libs/server-sent-events/src/client.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ class FoxyClient : public Client,
190190
if (connection_hook_) {
191191
connection_hook_(&req_);
192192
}
193+
194+
req_.prepare_payload();
195+
193196
session_->async_connect(
194197
host_, port_,
195198
beast::bind_front_handler(&FoxyClient::on_connect,
@@ -663,8 +666,6 @@ std::shared_ptr<Client> Builder::build() {
663666
}
664667
}
665668

666-
request.prepare_payload();
667-
668669
std::string host = uri_components->host();
669670

670671
request.set(http::field::host, host);

libs/server-sent-events/src/curl_client.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ void CurlClient::do_run() {
9393
request_context_->url = build_url(request_context_->req);
9494
}
9595

96+
request_context_->req.prepare_payload();
97+
9698
auto ctx = request_context_;
9799
auto weak_self = weak_from_this();
98100
std::weak_ptr<RequestContext> weak_ctx = ctx;

libs/server-sent-events/tests/client_test.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,3 +1370,67 @@ TEST(ClientTest, OnConnectHookSeesPreviousMutations) {
13701370
client->async_shutdown([&] { shutdown_latch.count_down(); });
13711371
EXPECT_TRUE(shutdown_latch.wait_for(5000ms));
13721372
}
1373+
1374+
TEST(ClientTest, OnConnectHookCanMutateBody) {
1375+
MockSSEServer server;
1376+
std::string received_body;
1377+
std::string received_content_length;
1378+
std::mutex received_mutex;
1379+
1380+
auto port = server.start([&](auto const& req, auto send_response,
1381+
auto send_sse_event, auto close) {
1382+
{
1383+
std::lock_guard lock(received_mutex);
1384+
received_body = req.body();
1385+
if (auto it = req.find(http::field::content_length);
1386+
it != req.end()) {
1387+
received_content_length = std::string(it->value());
1388+
}
1389+
}
1390+
http::response<http::string_body> res{http::status::ok, 11};
1391+
res.set(http::field::content_type, "text/event-stream");
1392+
res.chunked(true);
1393+
send_response(res);
1394+
send_sse_event(SSEFormatter::event("ok"));
1395+
std::this_thread::sleep_for(10ms);
1396+
close();
1397+
});
1398+
1399+
IoContextRunner runner;
1400+
EventCollector collector;
1401+
1402+
std::string const build_time_body = "short";
1403+
std::string const hook_body =
1404+
"this-body-is-much-longer-than-the-build-time-body";
1405+
ASSERT_GT(hook_body.size(), build_time_body.size());
1406+
1407+
auto client =
1408+
Builder(runner.context().get_executor(),
1409+
"http://localhost:" + std::to_string(port))
1410+
.receiver([&](Event e) { collector.add_event(std::move(e)); })
1411+
.method(http::verb::post)
1412+
.body(build_time_body)
1413+
.on_connect([&](http::request<http::string_body>* req) {
1414+
req->body() = hook_body;
1415+
})
1416+
.build();
1417+
1418+
// Connect; hook replaces the body with one larger than the build-time body.
1419+
client->async_connect();
1420+
1421+
// Verify the server received the full hook body and a matching
1422+
// Content-Length, not the stale build-time value.
1423+
ASSERT_TRUE(collector.wait_for_events(1));
1424+
{
1425+
std::lock_guard lock(received_mutex);
1426+
EXPECT_EQ(hook_body, received_body)
1427+
<< "Server received a truncated body. Content-Length header was '"
1428+
<< received_content_length << "' (hook set body of size "
1429+
<< hook_body.size() << ").";
1430+
EXPECT_EQ(std::to_string(hook_body.size()), received_content_length);
1431+
}
1432+
1433+
SimpleLatch shutdown_latch(1);
1434+
client->async_shutdown([&] { shutdown_latch.count_down(); });
1435+
EXPECT_TRUE(shutdown_latch.wait_for(5000ms));
1436+
}

0 commit comments

Comments
 (0)