Skip to content

Commit

Permalink
Merge pull request #787 from libcpr/put_read_callback
Browse files Browse the repository at this point in the history
Workaround for PUT requests with a read callback
  • Loading branch information
COM8 authored Jul 18, 2022
2 parents bda0a75 + d0448eb commit 871ed52
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 1 deletion.
10 changes: 9 additions & 1 deletion cpr/session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ void Session::prepareCommon() {

Response Session::makeRequest() {
if (!interceptors_.empty()) {
// At least one interceptor exists -> Ececute its intercept function
// At least one interceptor exists -> Execute its intercept function
std::shared_ptr<Interceptor> interceptor = interceptors_.front();
interceptors_.pop();
return interceptor->intercept(*this);
Expand Down Expand Up @@ -836,6 +836,14 @@ void Session::PreparePost() {

void Session::PreparePut() {
curl_easy_setopt(curl_->handle, CURLOPT_NOBODY, 0L);
if (!hasBodyOrPayload_ && readcb_.callback) {
/**
* Yes, this one has to be CURLOPT_POSTFIELDS even if we are performing a PUT request.
* In case we don't set this one, performing a POST-request with PUT won't work.
* It in theory this only enforces the usage of the readcallback for POST requests, but works here as well.
**/
curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDS, nullptr);
}
curl_easy_setopt(curl_->handle, CURLOPT_CUSTOMREQUEST, "PUT");
curl_easy_setopt(curl_->handle, CURLOPT_RANGE, nullptr);
prepareCommon();
Expand Down
31 changes: 31 additions & 0 deletions test/callback_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,37 @@ TEST(CallbackDataTests, CallbackReadFunctionTextTest) {
EXPECT_EQ(expected_text, response.text);
}

TEST(CallbackDataTests, CallbackReadFunctionTextTestPut) {
Url url{server->GetBaseUrl() + "/put.html"};
std::string expected_text{
"{\n"
" \"x\": 5\n"
"}"};
unsigned count = 0;
Response response = cpr::Put(url, cpr::ReadCallback{3, [&](char* buffer, size_t& size, intptr_t /*userdata*/) -> size_t {
std::string data;
++count;
switch (count) {
case 1:
data = "x=";
break;
case 2:
data = "5";
break;
default:
return false;
}
std::copy(data.begin(), data.end(), buffer);
size = data.size();
return true;
}});
EXPECT_EQ(2, count);
EXPECT_EQ(expected_text, response.text);
EXPECT_EQ(std::string{"application/json"}, response.header["content-type"]);
EXPECT_EQ(200, response.status_code);
EXPECT_EQ(ErrorCode::OK, response.error.code);
}

/**
* Checks if the "Transfer-Encoding" header will be kept when using headers and a read callback.
* Issue: https://github.com/whoshuu/cpr/issues/517
Expand Down

0 comments on commit 871ed52

Please sign in to comment.