Skip to content

Commit 2e9a4fb

Browse files
committed
Fix POST args with empty values not being parsed (issue #268)
Destroy post processor before invoking the callback to ensure pending POST body keys with empty values are properly finalized. Without this, POST data like "arg1=val1&arg2=" would fail to include arg2. The fix moves MHD_destroy_post_processor call to finalize_answer() before the resource callback is invoked, rather than waiting for the modded_request destructor. Added test cases verifying: - arg1=val1&arg2= correctly parses both args - arg1= correctly parses as empty string - arg1=&arg2= correctly parses both as empty strings This supersedes PR #269 with the requested code style changes.
1 parent f15a7b0 commit 2e9a4fb

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

src/webserver.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,10 @@ MHD_Result webserver::finalize_answer(MHD_Connection* connection, struct details
725725

726726
if (found) {
727727
try {
728+
if (mr->pp != nullptr) {
729+
MHD_destroy_post_processor(mr->pp);
730+
mr->pp = nullptr;
731+
}
728732
if (hrm->is_allowed(method)) {
729733
mr->dhrs = ((hrm)->*(mr->callback))(*mr->dhr); // copy in memory (move in case)
730734
if (mr->dhrs.get() == nullptr || mr->dhrs->get_response_code() == -1) {

test/integ/basic.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,62 @@ LT_BEGIN_AUTO_TEST(basic_suite, empty_arg)
991991
curl_easy_cleanup(curl);
992992
LT_END_AUTO_TEST(empty_arg)
993993

994+
LT_BEGIN_AUTO_TEST(basic_suite, empty_arg_value_at_end)
995+
// Test for issue #268: POST body keys without values at the end
996+
// are not processed when using application/x-www-form-urlencoded
997+
simple_resource resource;
998+
LT_ASSERT_EQ(true, ws->register_resource("base", &resource));
999+
curl_global_init(CURL_GLOBAL_ALL);
1000+
1001+
// Test case 1: arg2 has empty value at end (the bug case)
1002+
{
1003+
string s;
1004+
CURL *curl = curl_easy_init();
1005+
CURLcode res;
1006+
curl_easy_setopt(curl, CURLOPT_URL, "localhost:" PORT_STRING "/base");
1007+
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "arg1=val1&arg2=");
1008+
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
1009+
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
1010+
res = curl_easy_perform(curl);
1011+
LT_ASSERT_EQ(res, 0);
1012+
// arg1="val1", arg2="" -> response should be "val1"
1013+
LT_CHECK_EQ(s, "val1");
1014+
curl_easy_cleanup(curl);
1015+
}
1016+
1017+
// Test case 2: only arg1 with empty value
1018+
{
1019+
string s;
1020+
CURL *curl = curl_easy_init();
1021+
CURLcode res;
1022+
curl_easy_setopt(curl, CURLOPT_URL, "localhost:" PORT_STRING "/base");
1023+
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "arg1=");
1024+
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
1025+
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
1026+
res = curl_easy_perform(curl);
1027+
LT_ASSERT_EQ(res, 0);
1028+
// arg1="" -> response should be ""
1029+
LT_CHECK_EQ(s, "");
1030+
curl_easy_cleanup(curl);
1031+
}
1032+
1033+
// Test case 3: both args with empty values
1034+
{
1035+
string s;
1036+
CURL *curl = curl_easy_init();
1037+
CURLcode res;
1038+
curl_easy_setopt(curl, CURLOPT_URL, "localhost:" PORT_STRING "/base");
1039+
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "arg1=&arg2=");
1040+
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
1041+
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
1042+
res = curl_easy_perform(curl);
1043+
LT_ASSERT_EQ(res, 0);
1044+
// arg1="", arg2="" -> response should be ""
1045+
LT_CHECK_EQ(s, "");
1046+
curl_easy_cleanup(curl);
1047+
}
1048+
LT_END_AUTO_TEST(empty_arg_value_at_end)
1049+
9941050
LT_BEGIN_AUTO_TEST(basic_suite, no_response)
9951051
no_response_resource resource;
9961052
LT_ASSERT_EQ(true, ws->register_resource("base", &resource));

0 commit comments

Comments
 (0)