Skip to content

Commit

Permalink
Add method SetAcceptEncoding for customized Accept-Encoding header (#683
Browse files Browse the repository at this point in the history
)
  • Loading branch information
leviliangtw committed May 18, 2022
1 parent 5e64f82 commit 021210a
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 2 deletions.
1 change: 1 addition & 0 deletions cpr/CMakeLists.txt
@@ -1,6 +1,7 @@
cmake_minimum_required(VERSION 3.15)

add_library(cpr
accept_encoding.cpp
auth.cpp
bearer.cpp
cookies.cpp
Expand Down
23 changes: 23 additions & 0 deletions cpr/accept_encoding.cpp
@@ -0,0 +1,23 @@
#include "cpr/accept_encoding.h"

namespace cpr {

AcceptEncoding::AcceptEncoding(const std::initializer_list<AcceptEncodingMethods>& methods) : methods_{methods} {}

bool AcceptEncoding::isEmpty() const {
return methods_.empty();
}

const std::string& AcceptEncoding::getString() const {
std::string* accept_encoding = new std::string();
for (AcceptEncodingMethods method : methods_) {
*accept_encoding += AcceptEncoding::MethodsString.at(method) + ", ";
}
if (!accept_encoding->empty()) {
accept_encoding->pop_back();
accept_encoding->pop_back();
}
return *accept_encoding;
}

} // namespace cpr
15 changes: 13 additions & 2 deletions cpr/session.cpp
Expand Up @@ -68,6 +68,7 @@ class Session::Impl {
void SetRange(const Range& range);
void SetMultiRange(const MultiRange& multi_range);
void SetReserveSize(const ReserveSize& reserve_size);
void SetAcceptEncoding(const AcceptEncoding& accept_encoding);

cpr_off_t GetDownloadFileLength();
void ResponseStringReserve(size_t size);
Expand Down Expand Up @@ -103,6 +104,7 @@ class Session::Impl {
Proxies proxies_;
ProxyAuthentication proxyAuth_;
Header header_;
AcceptEncoding acceptEncoding_;
/**
* Will be set by the read callback.
* Ensures that the "Transfer-Encoding" is set to "chunked", if not overriden in header_.
Expand Down Expand Up @@ -570,6 +572,10 @@ void Session::Impl::SetReserveSize(const ReserveSize& reserve_size) {
ResponseStringReserve(reserve_size.size);
}

void Session::Impl::SetAcceptEncoding(const AcceptEncoding& accept_encoding) {
acceptEncoding_ = accept_encoding;
}

void Session::Impl::PrepareDelete() {
curl_easy_setopt(curl_->handle, CURLOPT_HTTPGET, 0L);
curl_easy_setopt(curl_->handle, CURLOPT_NOBODY, 0L);
Expand Down Expand Up @@ -792,8 +798,11 @@ void Session::Impl::prepareCommon() {

#if LIBCURL_VERSION_MAJOR >= 7
#if LIBCURL_VERSION_MINOR >= 21
/* enable all supported built-in compressions */
curl_easy_setopt(curl_->handle, CURLOPT_ACCEPT_ENCODING, "");
if (acceptEncoding_.isEmpty())
/* enable all supported built-in compressions */
curl_easy_setopt(curl_->handle, CURLOPT_ACCEPT_ENCODING, "");
else
curl_easy_setopt(curl_->handle, CURLOPT_ACCEPT_ENCODING, acceptEncoding_.getString().c_str());
#endif
#endif

Expand Down Expand Up @@ -883,6 +892,7 @@ void Session::SetHttpVersion(const HttpVersion& version) { pimpl_->SetHttpVersio
void Session::SetRange(const Range& range) { pimpl_->SetRange(range); }
void Session::SetMultiRange(const MultiRange& multi_range) { pimpl_->SetMultiRange(multi_range); }
void Session::SetReserveSize(const ReserveSize& reserve_size) { pimpl_->SetReserveSize(reserve_size); }
void Session::SetAcceptEncoding(const AcceptEncoding& accept_encoding) { pimpl_->SetAcceptEncoding(accept_encoding); }
void Session::SetOption(const ReadCallback& read) { pimpl_->SetReadCallback(read); }
void Session::SetOption(const HeaderCallback& header) { pimpl_->SetHeaderCallback(header); }
void Session::SetOption(const WriteCallback& write) { pimpl_->SetWriteCallback(write); }
Expand Down Expand Up @@ -924,6 +934,7 @@ void Session::SetOption(const HttpVersion& version) { pimpl_->SetHttpVersion(ver
void Session::SetOption(const Range& range) { pimpl_->SetRange(range); }
void Session::SetOption(const MultiRange& multi_range) { pimpl_->SetMultiRange(multi_range); }
void Session::SetOption(const ReserveSize& reserve_size) { pimpl_->SetReserveSize(reserve_size.size); }
void Session::SetOption(const AcceptEncoding& accept_encoding) { pimpl_->SetAcceptEncoding(accept_encoding); }

cpr_off_t Session::GetDownloadFileLength() { return pimpl_->GetDownloadFileLength(); }
void Session::ResponseStringReserve(size_t size) { pimpl_->ResponseStringReserve(size); }
Expand Down
1 change: 1 addition & 0 deletions include/CMakeLists.txt
Expand Up @@ -7,6 +7,7 @@ target_include_directories(cpr PUBLIC

target_sources(cpr PRIVATE
# Header files (useful in IDEs)
cpr/accept_encoding.h
cpr/api.h
cpr/auth.h
cpr/bearer.h
Expand Down
40 changes: 40 additions & 0 deletions include/cpr/accept_encoding.h
@@ -0,0 +1,40 @@
#ifndef CPR_ACCEPT_ENCODING_H
#define CPR_ACCEPT_ENCODING_H

#include <curl/curlver.h>
#include <initializer_list>
#include <map>
#include <string>
#include <vector>

namespace cpr {

enum class AcceptEncodingMethods {
identity,
deflate,
zlib,
gzip,
};

class AcceptEncoding {
public:
std::map<AcceptEncodingMethods, std::string> MethodsString {
{AcceptEncodingMethods::identity, "identity"},
{AcceptEncodingMethods::deflate, "deflate"},
{AcceptEncodingMethods::zlib, "zlib"},
{AcceptEncodingMethods::gzip, "gzip"}
};

AcceptEncoding() = default;
AcceptEncoding(const std::initializer_list<AcceptEncodingMethods>& methods);

bool isEmpty() const;
const std::string& getString() const;

private:
std::vector<AcceptEncodingMethods> methods_;
};

} // namespace cpr

#endif
3 changes: 3 additions & 0 deletions include/cpr/session.h
Expand Up @@ -13,6 +13,7 @@
#include "cpr/cookies.h"
#include "cpr/cprtypes.h"
#include "cpr/curlholder.h"
#include "cpr/accept_encoding.h"
#include "cpr/http_version.h"
#include "cpr/interface.h"
#include "cpr/limit_rate.h"
Expand Down Expand Up @@ -81,6 +82,7 @@ class Session {
void SetRange(const Range& range);
void SetMultiRange(const MultiRange& multi_range);
void SetReserveSize(const ReserveSize& reserve_size);
void SetAcceptEncoding(const AcceptEncoding& accept_encoding);

// Used in templated functions
void SetOption(const Url& url);
Expand Down Expand Up @@ -124,6 +126,7 @@ class Session {
void SetOption(const Range& range);
void SetOption(const MultiRange& multi_range);
void SetOption(const ReserveSize& reserve_size);
void SetOption(const AcceptEncoding& accept_encoding);

cpr_off_t GetDownloadFileLength();
/**
Expand Down
18 changes: 18 additions & 0 deletions test/httpServer.cpp
Expand Up @@ -756,6 +756,22 @@ void HttpServer::OnRequestDownloadGzip(mg_connection* conn, http_message* msg) {
}
}

void HttpServer::OnRequestCheckAcceptEncoding(mg_connection* conn, http_message* msg) {
std::string response;
for (size_t i = 0; i < sizeof(msg->header_names) / sizeof(mg_str); i++) {
if (!msg->header_names[i].p) {
continue;
}
std::string name = std::string(msg->header_names[i].p, msg->header_names[i].len);
if (std::string{"Accept-Encoding"} == name) {
response = std::string(msg->header_values[i].p, msg->header_values[i].len);
}
}
std::string headers = "Content-Type: text/html";
mg_send_head(conn, 200, response.length(), headers.c_str());
mg_send(conn, response.c_str(), response.length());
}

void HttpServer::OnRequest(mg_connection* conn, http_message* msg) {
std::string uri = std::string(msg->uri.p, msg->uri.len);
if (uri == "/") {
Expand Down Expand Up @@ -820,6 +836,8 @@ void HttpServer::OnRequest(mg_connection* conn, http_message* msg) {
OnRequestPatchNotAllowed(conn, msg);
} else if (uri == "/download_gzip.html") {
OnRequestDownloadGzip(conn, msg);
} else if (uri == "/check_accept_encoding.html") {
OnRequestCheckAcceptEncoding(conn, msg);
} else {
OnRequestNotFound(conn, msg);
}
Expand Down
1 change: 1 addition & 0 deletions test/httpServer.hpp
Expand Up @@ -51,6 +51,7 @@ class HttpServer : public AbstractServer {
static void OnRequestPatch(mg_connection* conn, http_message* msg);
static void OnRequestPatchNotAllowed(mg_connection* conn, http_message* msg);
static void OnRequestDownloadGzip(mg_connection* conn, http_message* msg);
static void OnRequestCheckAcceptEncoding(mg_connection* conn, http_message* msg);

protected:
mg_connection* initServer(mg_mgr* mgr, MG_CB(mg_event_handler_t event_handler, void* user_data)) override;
Expand Down
14 changes: 14 additions & 0 deletions test/session_tests.cpp
Expand Up @@ -940,6 +940,20 @@ TEST(BasicTests, ReserveResponseString) {
EXPECT_EQ(ErrorCode::OK, response.error.code);
}

TEST(BasicTests, AcceptEncodingTest) {
Url url{server->GetBaseUrl() + "/check_accept_encoding.html"};
Session session;
session.SetUrl(url);
session.SetAcceptEncoding({{AcceptEncodingMethods::deflate, AcceptEncodingMethods::gzip, AcceptEncodingMethods::zlib}});
Response response = session.Get();
std::string expected_text{"deflate, gzip, zlib"};
EXPECT_EQ(expected_text, response.text);
EXPECT_EQ(url, response.url);
EXPECT_EQ(std::string{"text/html"}, response.header["content-type"]);
EXPECT_EQ(200, 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

0 comments on commit 021210a

Please sign in to comment.