Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,6 @@ compile_commands.json

# macOS
.DS_Store

# CLion
.idea/
16 changes: 15 additions & 1 deletion cpr/session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,10 @@ void Session::RemoveContent() {
curl_mime_free(curl_->multipart);
curl_->multipart = nullptr;
}
} else if (std::holds_alternative<cpr::BodyView>(content_)) {
// set default values, so curl does not send a body in subsequent requests
curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDSIZE_LARGE, -1);
curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDS, nullptr);
}
content_ = std::monostate{};
}
Expand Down Expand Up @@ -488,6 +492,11 @@ void Session::SetBody(Body&& body) {
content_ = std::move(body);
}

void Session::SetBodyView(BodyView body) {
static_assert(std::is_trivially_copyable_v<BodyView>, "BodyView expected to be trivially copyable otherwise will need some std::move across codebase");
content_ = body;
}

void Session::SetLowSpeed(const LowSpeed& low_speed) {
curl_easy_setopt(curl_->handle, CURLOPT_LOW_SPEED_LIMIT, low_speed.limit);
curl_easy_setopt(curl_->handle, CURLOPT_LOW_SPEED_TIME, low_speed.time); // cppcheck-suppress y2038-unsafe-call
Expand Down Expand Up @@ -971,6 +980,10 @@ void Session::prepareBodyPayloadOrMultipart() const {
const std::string& body = std::get<cpr::Body>(content_).str();
curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDSIZE_LARGE, static_cast<curl_off_t>(body.length()));
curl_easy_setopt(curl_->handle, CURLOPT_COPYPOSTFIELDS, body.c_str());
} else if (std::holds_alternative<cpr::BodyView>(content_)) {
const std::string_view body = std::get<cpr::BodyView>(content_).str();
curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDSIZE_LARGE, static_cast<curl_off_t>(body.length()));
curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDS, body.data());
} else if (std::holds_alternative<cpr::Multipart>(content_)) {
// Make sure, we have a empty multipart to start with:
if (curl_->multipart) {
Expand Down Expand Up @@ -1020,7 +1033,7 @@ void Session::prepareBodyPayloadOrMultipart() const {
}

[[nodiscard]] bool Session::hasBodyOrPayload() const {
return std::holds_alternative<cpr::Body>(content_) || std::holds_alternative<cpr::Payload>(content_);
return std::holds_alternative<cpr::Body>(content_) || std::holds_alternative<cpr::BodyView>(content_) || std::holds_alternative<cpr::Payload>(content_);
}

// clang-format off
Expand Down Expand Up @@ -1057,6 +1070,7 @@ void Session::SetOption(const Redirect& redirect) { SetRedirect(redirect); }
void Session::SetOption(const Cookies& cookies) { SetCookies(cookies); }
void Session::SetOption(const Body& body) { SetBody(body); }
void Session::SetOption(Body&& body) { SetBody(std::move(body)); }
void Session::SetOption(BodyView body) { SetBodyView(body); }
void Session::SetOption(const LowSpeed& low_speed) { SetLowSpeed(low_speed); }
void Session::SetOption(const VerifySsl& verify) { SetVerifySsl(verify); }
void Session::SetOption(const Verbose& verbose) { SetVerbose(verbose); }
Expand Down
1 change: 1 addition & 0 deletions include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ target_sources(cpr PRIVATE
cpr/auth.h
cpr/bearer.h
cpr/body.h
cpr/body_view.h
cpr/buffer.h
cpr/cert_info.h
cpr/cookies.h
Expand Down
1 change: 0 additions & 1 deletion include/cpr/body.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include <fstream>
#include <initializer_list>
#include <string>
#include <vector>

#include "cpr/buffer.h"
#include "cpr/cprtypes.h"
Expand Down
36 changes: 36 additions & 0 deletions include/cpr/body_view.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#ifndef CPR_BODY_VIEW_H
#define CPR_BODY_VIEW_H

#include <string_view>

#include "cpr/buffer.h"

namespace cpr {

class BodyView final {
public:
BodyView() = default;
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
BodyView(std::string_view body) : m_body(body) {}
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
BodyView(const char* body) : m_body(body) {}
BodyView(const char* str, size_t len) : m_body(str, len) {}
// NOLINTNEXTLINE(google-explicit-constructor, cppcoreguidelines-pro-type-reinterpret-cast)
BodyView(const Buffer& buffer) : m_body(reinterpret_cast<const char*>(buffer.data), static_cast<size_t>(buffer.datalen)) {}

BodyView(const BodyView& other) = default;
BodyView(BodyView&& old) noexcept = default;
~BodyView() = default;

BodyView& operator=(BodyView&& old) noexcept = default;
BodyView& operator=(const BodyView& other) = default;

[[nodiscard]] std::string_view str() const { return m_body; }

private:
std::string_view m_body;
};

} // namespace cpr

#endif
5 changes: 4 additions & 1 deletion include/cpr/session.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "cpr/auth.h"
#include "cpr/bearer.h"
#include "cpr/body.h"
#include "cpr/body_view.h"
#include "cpr/callback.h"
#include "cpr/connect_timeout.h"
#include "cpr/cookies.h"
Expand Down Expand Up @@ -46,7 +47,7 @@
namespace cpr {

using AsyncResponse = AsyncWrapper<Response>;
using Content = std::variant<std::monostate, cpr::Payload, cpr::Body, cpr::Multipart>;
using Content = std::variant<std::monostate, cpr::Payload, cpr::Body, cpr::BodyView, cpr::Multipart>;

class Interceptor;
class MultiPerform;
Expand Down Expand Up @@ -90,6 +91,7 @@ class Session : public std::enable_shared_from_this<Session> {
void SetCookies(const Cookies& cookies);
void SetBody(Body&& body);
void SetBody(const Body& body);
void SetBodyView(BodyView body);
void SetLowSpeed(const LowSpeed& low_speed);
void SetVerifySsl(const VerifySsl& verify);
void SetUnixSocket(const UnixSocket& unix_socket);
Expand Down Expand Up @@ -154,6 +156,7 @@ class Session : public std::enable_shared_from_this<Session> {
void SetOption(const Cookies& cookies);
void SetOption(Body&& body);
void SetOption(const Body& body);
void SetOption(BodyView body);
void SetOption(const ReadCallback& read);
void SetOption(const HeaderCallback& header);
void SetOption(const WriteCallback& write);
Expand Down
14 changes: 14 additions & 0 deletions test/raw_body_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,20 @@ TEST(BodyPostTests, StringMoveBodyTest) {
EXPECT_EQ(ErrorCode::OK, response.error.code);
}

TEST(BodyPostTests, BodyViewTest) {
const Url url{server->GetBaseUrl() + "/url_post.html"};
Response response = cpr::Post(url, BodyView{"x=5"});
const std::string expected_text{
"{\n"
" \"x\": 5\n"
"}"};
EXPECT_EQ(expected_text, response.text);
EXPECT_EQ(url, response.url);
EXPECT_EQ(std::string{"application/json"}, response.header["content-type"]);
EXPECT_EQ(201, response.status_code);
EXPECT_EQ(ErrorCode::OK, response.error.code);
}

int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
::testing::AddGlobalTestEnvironment(server);
Expand Down
17 changes: 17 additions & 0 deletions test/session_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,23 @@ TEST(BodyTests, SetBodyValueTest) {
EXPECT_EQ(ErrorCode::OK, response.error.code);
}

TEST(BodyTests, SetBodyViewTest) {
const Url url{server->GetBaseUrl() + "/url_post.html"};
Session session;
session.SetUrl(url);
session.SetBodyView(BodyView{"x=5"});
Response response = session.Post();
const std::string expected_text{
"{\n"
" \"x\": 5\n"
"}"};
EXPECT_EQ(expected_text, response.text);
EXPECT_EQ(url, response.url);
EXPECT_EQ(std::string{"application/json"}, response.header["content-type"]);
EXPECT_EQ(201, response.status_code);
EXPECT_EQ(ErrorCode::OK, response.error.code);
}

TEST(DigestTests, SetDigestTest) {
Url url{server->GetBaseUrl() + "/digest_auth.html"};
Session session;
Expand Down
Loading