From 7d1db7d3ebf8a29b0ce14ed3e583a461ba15b6b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Levent=20KARAG=C3=96L?= Date: Sun, 21 Apr 2024 07:26:21 +0300 Subject: [PATCH 1/7] Method overloading structure converted to Builder Pattern --- examples/main.cpp | 106 +++++---- src/libcpp-http-client.hpp | 460 ++++++++----------------------------- test/test.cpp | 303 +++++++++++++----------- 3 files changed, 329 insertions(+), 540 deletions(-) diff --git a/examples/main.cpp b/examples/main.cpp index b00272c..93ec58f 100644 --- a/examples/main.cpp +++ b/examples/main.cpp @@ -5,10 +5,13 @@ using namespace lklibs; void simpleGet() { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/get"); // The simplest but slowest method if multiple calls will be made - auto response = httpClient.getRequest("https://httpbun.com/get?param1=7¶m2=test").get(); + auto response = httpClient + .setQueryString("param1=7¶m2=test") + .send() + .get(); std::cout << "Succeed: " << response.succeed << std::endl; std::cout << "Http Status Code: " << response.statusCode << std::endl; @@ -17,12 +20,14 @@ void simpleGet() { void nonBlockingGet() { - HttpClient httpClient; + HttpClient httpClient1("https://httpbun.com/get"); + HttpClient httpClient2("https://httpbun.com/get"); + HttpClient httpClient3("https://httpbun.com/get"); // All requests are made one after the other without waiting for a response - auto future1 = httpClient.getRequest("https://httpbun.com/get?param1=1¶m2=test1"); - auto future2 = httpClient.getRequest("https://httpbun.com/get?param1=2¶m2=test2"); - auto future3 = httpClient.getRequest("https://httpbun.com/get?param1=3¶m2=test3"); + auto future1 = httpClient1.setQueryString("param1=1¶m2=test1").send(); + auto future2 = httpClient2.setQueryString("param1=2¶m2=test2").send(); + auto future3 = httpClient3.setQueryString("param1=3¶m2=test3").send(); // Then all the answers are received. Thus, 3 requests are sent in parallel auto response1 = future1.get(); @@ -44,10 +49,13 @@ void nonBlockingGet() { void receiveBinaryData() { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/bytes/100"); - // If you need to retrieve binary data such as an image, just pass the "returnAsBinary" parameter as true - auto response = httpClient.getRequest("https://httpbun.com/bytes/100", true).get(); + // If you need to retrieve binary data such as an image, just call the "returnAsBinary" method + auto response = httpClient + .returnAsBinary() + .send() + .get(); std::cout << "Succeed: " << response.succeed << std::endl; std::cout << "Http Status Code: " << response.statusCode << std::endl; @@ -58,10 +66,10 @@ void receiveBinaryData() { void receiveError() { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/not_found"); // This is an exception free library. If an error occurs, no exception is thrown - auto response = httpClient.getRequest("https://httpbun.com/not_found").get(); + auto response = httpClient.send().get(); // Instead, the succeed field of the response object is set to false std::cout << "Succeed: " << response.succeed << std::endl; @@ -75,27 +83,28 @@ void receiveError() { void sendingHttpHeaders() { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/get?param1=7¶m2=test"); - // You can send custom headers in a string/string map - auto headers = std::map(); - - headers["Custom-Header1"] = "value1"; - headers["Custom-Header2"] = "value2"; - - auto response = httpClient.getRequest("https://httpbun.com/get?param1=7¶m2=test", headers).get(); + // You can send custom headers as key-value pairs + auto response = httpClient + .addHeader("Custom-Header1", "value1") + .addHeader("Custom-Header2", "value2") + .send() + .get(); std::cout << "Succeed: " << response.succeed << std::endl; } void simplePostWithFormData() { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/post"); // You can send a POST request with form data in the payload - std::string payload = "param1=7¶m2=test"; - - auto response = httpClient.postRequest("https://httpbun.com/post", payload).get(); + auto response = httpClient + .setMethod(HttpMethod::POST) + .setPayload("param1=7¶m2=test") + .send() + .get(); std::cout << "Succeed: " << response.succeed << std::endl; std::cout << "Http Status Code: " << response.statusCode << std::endl; @@ -104,16 +113,15 @@ void simplePostWithFormData() { void simplePostWithJSONData() { - HttpClient httpClient; - - std::string payload = R"({"param1": 7, "param2": "test"})"; + HttpClient httpClient("https://httpbun.com/post"); // You need to send the "Content-Type" as "application/json" in the HTTP Header, if you need to send json data in the payload - auto headers = std::map(); - - headers["Content-Type"] = "application/json"; - - auto response = httpClient.postRequest("https://httpbun.com/post", payload, headers).get(); + auto response = httpClient + .setMethod(HttpMethod::POST) + .setPayload(R"({"param1": 7, "param2": "test"})") + .addHeader("Content-Type", "application/json") + .send() + .get(); std::cout << "Succeed: " << response.succeed << std::endl; std::cout << "Http Status Code: " << response.statusCode << std::endl; @@ -122,12 +130,14 @@ void simplePostWithJSONData() { void simplePutWithFormData() { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/put"); // You can send a PUT request with form data in the payload just like POST - std::string payload = "param1=7¶m2=test"; - - auto response = httpClient.putRequest("https://httpbun.com/put", payload).get(); + auto response = httpClient + .setMethod(HttpMethod::PUT) + .setPayload("param1=7¶m2=test") + .send() + .get(); std::cout << "Succeed: " << response.succeed << std::endl; std::cout << "Http Status Code: " << response.statusCode << std::endl; @@ -136,12 +146,14 @@ void simplePutWithFormData() { void simpleDeleteWithFormData() { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/delete"); // You can send a DELETE request with form data in the payload just like POST - std::string payload = "param1=7¶m2=test"; - - auto response = httpClient.deleteRequest("https://httpbun.com/delete", payload).get(); + auto response = httpClient + .setMethod(HttpMethod::DELETE_) + .setPayload("param1=7¶m2=test") + .send() + .get(); std::cout << "Succeed: " << response.succeed << std::endl; std::cout << "Http Status Code: " << response.statusCode << std::endl; @@ -150,10 +162,14 @@ void simpleDeleteWithFormData() { void simplePatch() { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/patch"); // You can send a PATCH request with QueryString just like GET - auto response = httpClient.patchRequest("https://httpbun.com/patch?param1=7¶m2=test").get(); + auto response = httpClient + .setMethod(HttpMethod::PATCH) + .setQueryString("param1=7¶m2=test") + .send() + .get(); std::cout << "Succeed: " << response.succeed << std::endl; std::cout << "Http Status Code: " << response.statusCode << std::endl; @@ -162,12 +178,10 @@ void simplePatch() { void ignoreSslErrors() { - HttpClient httpClient; - - // If you need to ignore SSL errors, you can set the "ignoreSslErrors" field to true - httpClient.ignoreSslErrors = true; + HttpClient httpClient("https://self-signed-cert.httpbun.com"); - auto response = httpClient.getRequest("https://self-signed-cert.httpbun.com").get(); + // If you need to ignore SSL errors, you can call "ignoreSslErrors" method before sending the request + auto response = httpClient.ignoreSslErrors().send().get(); std::cout << "Succeed: " << response.succeed << std::endl; std::cout << "Http Status Code: " << response.statusCode << std::endl; diff --git a/src/libcpp-http-client.hpp b/src/libcpp-http-client.hpp index f2799df..5496181 100644 --- a/src/libcpp-http-client.hpp +++ b/src/libcpp-http-client.hpp @@ -1,7 +1,7 @@ /* Modern non-blocking HTTP Client library for C++ (17+) -version 1.1.0 +version 1.2.0 https://github.com/lk-libs/libcpp-http-client If you encounter any issues, please submit a ticket at https://github.com/lk-libs/libcpp-http-client/issues @@ -77,426 +77,158 @@ namespace lklibs { : succeed(succeed), textData(std::move(textData)), binaryData(std::move(binaryData)), statusCode(statusCode), errorMessage(std::move(errorMessage)) {} }; + /** + * @brief HTTP Method options for the request + */ + enum class HttpMethod { + GET, + POST, + PUT, + DELETE_, + PATCH + }; + /** * @brief HTTP client class that makes asynchronous HTTP requests */ class HttpClient { public: - HttpClient() { - curl_global_init(CURL_GLOBAL_DEFAULT); - } - - ~HttpClient() { - curl_global_cleanup(); - } - - /** - * @brief Ignore SSL errors when making HTTP requests - */ - bool ignoreSslErrors = false; - - /** - * @brief Makes an HTTP GET request for the given URL and returns the result - * - * @param url: Request URL - * @return Result of the request (see HttpResult object for details) - */ - std::future getRequest(const std::string &url) noexcept { - - return request(url, "GET", "", false, {}); - } - - /** - * @brief Makes an HTTP GET request for the given URL and returns the result - * - * @param url: Request URL - * @param returnAsBinary: Return result as binary instead of string - * @return Result of the request (see HttpResult object for details) - */ - std::future getRequest(const std::string &url, bool returnAsBinary) noexcept { - - return request(url, "GET", "", returnAsBinary, {}); - } - - /** - * @brief Makes an HTTP GET request for the given URL and returns the result - * - * @param url: Request URL - * @param headers: HTTP Header information to be sent when making the request - * @return Result of the request (see HttpResult object for details) - */ - std::future getRequest(const std::string &url, const std::map &headers) noexcept { - - return request(url, "GET", "", false, headers); - } - - /** - * @brief Makes an HTTP GET request for the given URL and returns the result - * - * @param url: Request URL - * @param returnAsBinary: Return result as binary instead of string - * @param headers: HTTP Header information to be sent when making the request - * @return Result of the request (see HttpResult object for details) - */ - std::future getRequest(const std::string &url, bool returnAsBinary, const std::map &headers) noexcept { - - return request(url, "GET", "", returnAsBinary, headers); - } - - - /** - * @brief Makes an HTTP POST request for the given URL and returns the result - * - * @param url: Request URL - * @return Result of the request (see HttpResult object for details) - */ - std::future postRequest(const std::string &url) noexcept { - - return request(url, "POST", "", false, {}); - } - - /** - * @brief Makes an HTTP POST request for the given URL and returns the result - * - * @param url: Request URL - * @param payload: Payload to be sent with the request - * @return Result of the request (see HttpResult object for details) - */ - std::future postRequest(const std::string &url, const std::string &payload) noexcept { - - return request(url, "POST", payload, false, {}); - } - - /** - * @brief Makes an HTTP POST request for the given URL and returns the result - * - * @param url: Request URL - * @param returnAsBinary: Return result as binary instead of string - * @return Result of the request (see HttpResult object for details) - */ - std::future postRequest(const std::string &url, bool returnAsBinary) noexcept { - - return request(url, "POST", "", returnAsBinary, {}); - } - /** - * @brief Makes an HTTP POST request for the given URL and returns the result + * @brief Constructor for the HttpClient class * - * @param url: Request URL - * @param headers: HTTP Header information to be sent when making the request - * @return Result of the request (see HttpResult object for details) + * @param url: URL for the request */ - std::future postRequest(const std::string &url, const std::map &headers) noexcept { + explicit HttpClient(const std::string &url) { - return request(url, "POST", "", false, headers); - } - - /** - * @brief Makes an HTTP POST request for the given URL and returns the result - * - * @param url: Request URL - * @param payload: Payload to be sent with the request - * @param returnAsBinary: Return result as binary instead of string - * @return Result of the request (see HttpResult object for details) - */ - std::future postRequest(const std::string &url, const std::string &payload, bool returnAsBinary) noexcept { + this->url = url; - return request(url, "POST", payload, returnAsBinary, {}); - } - - /** - * @brief Makes an HTTP POST request for the given URL and returns the result - * - * @param url: Request URL - * @param payload: Payload to be sent with the request - * @param headers: HTTP Header information to be sent when making the request - * @return Result of the request (see HttpResult object for details) - */ - std::future postRequest(const std::string &url, const std::string &payload, const std::map &headers) noexcept { - - return request(url, "POST", payload, false, headers); - } - - /** - * @brief Makes an HTTP POST request for the given URL and returns the result - * - * @param url: Request URL - * @param returnAsBinary: Return result as binary instead of string - * @param headers: HTTP Header information to be sent when making the request - * @return Result of the request (see HttpResult object for details) - */ - std::future postRequest(const std::string &url, bool returnAsBinary, const std::map &headers) noexcept { - - return request(url, "POST", "", returnAsBinary, headers); - } - - /** - * @brief Makes an HTTP POST request for the given URL and returns the result - * - * @param url: Request URL - * @param payload: Payload to be sent with the request - * @param returnAsBinary: Return result as binary instead of string - * @param headers: HTTP Header information to be sent when making the request - * @return Result of the request (see HttpResult object for details) - */ - std::future postRequest(const std::string &url, const std::string &payload, bool returnAsBinary, const std::map &headers) noexcept { - - return request(url, "POST", payload, returnAsBinary, headers); - } - - - /** - * @brief Makes an HTTP PUT request for the given URL and returns the result - * - * @param url: Request URL - * @return Result of the request (see HttpResult object for details) - */ - std::future putRequest(const std::string &url) noexcept { - - return request(url, "PUT", "", false, {}); - } - - /** - * @brief Makes an HTTP PUT request for the given URL and returns the result - * - * @param url: Request URL - * @param payload: Payload to be sent with the request - * @return Result of the request (see HttpResult object for details) - */ - std::future putRequest(const std::string &url, const std::string &payload) noexcept { - - return request(url, "PUT", payload, false, {}); - } - - /** - * @brief Makes an HTTP PUT request for the given URL and returns the result - * - * @param url: Request URL - * @param returnAsBinary: Return result as binary instead of string - * @return Result of the request (see HttpResult object for details) - */ - std::future putRequest(const std::string &url, bool returnAsBinary) noexcept { - - return request(url, "PUT", "", returnAsBinary, {}); + curl_global_init(CURL_GLOBAL_DEFAULT); } - /** - * @brief Makes an HTTP PUT request for the given URL and returns the result - * - * @param url: Request URL - * @param headers: HTTP Header information to be sent when making the request - * @return Result of the request (see HttpResult object for details) - */ - std::future putRequest(const std::string &url, const std::map &headers) noexcept { - - return request(url, "PUT", "", false, headers); + ~HttpClient() { + curl_global_cleanup(); } /** - * @brief Makes an HTTP PUT request for the given URL and returns the result + * @brief Set the HTTP method for the request * - * @param url: Request URL - * @param payload: Payload to be sent with the request - * @param returnAsBinary: Return result as binary instead of string - * @return Result of the request (see HttpResult object for details) + * @param method: HTTP method to be used for the request */ - std::future putRequest(const std::string &url, const std::string &payload, bool returnAsBinary) noexcept { + HttpClient &setMethod(const HttpMethod &method) { - return request(url, "PUT", payload, returnAsBinary, {}); - } - - /** - * @brief Makes an HTTP PUT request for the given URL and returns the result - * - * @param url: Request URL - * @param payload: Payload to be sent with the request - * @param headers: HTTP Header information to be sent when making the request - * @return Result of the request (see HttpResult object for details) - */ - std::future putRequest(const std::string &url, const std::string &payload, const std::map &headers) noexcept { + this->method = [method] { + switch (method) { + case HttpMethod::GET: + return "GET"; + case HttpMethod::POST: + return "POST"; + case HttpMethod::PUT: + return "PUT"; + case HttpMethod::DELETE_: + return "DELETE"; + case HttpMethod::PATCH: + return "PATCH"; + default: + return "GET"; + } + }(); - return request(url, "PUT", payload, false, headers); + return *this; } /** - * @brief Makes an HTTP PUT request for the given URL and returns the result + * @brief Set the query string for the request * - * @param url: Request URL - * @param returnAsBinary: Return result as binary instead of string - * @param headers: HTTP Header information to be sent when making the request - * @return Result of the request (see HttpResult object for details) + * @param queryString: Query string to be sent with the request */ - std::future putRequest(const std::string &url, bool returnAsBinary, const std::map &headers) noexcept { - - return request(url, "PUT", "", returnAsBinary, headers); - } + HttpClient &setQueryString(const std::string &queryString) { - /** - * @brief Makes an HTTP PUT request for the given URL and returns the result - * - * @param url: Request URL - * @param payload: Payload to be sent with the request - * @param returnAsBinary: Return result as binary instead of string - * @param headers: HTTP Header information to be sent when making the request - * @return Result of the request (see HttpResult object for details) - */ - std::future putRequest(const std::string &url, const std::string &payload, bool returnAsBinary, const std::map &headers) noexcept { + if (this->url.find('?') != std::string::npos) { - return request(url, "PUT", payload, returnAsBinary, headers); - } + this->url += "&" + queryString; + } else { - /** - * @brief Makes an HTTP DELETE request for the given URL and returns the result - * - * @param url: Request URL - * @return Result of the request (see HttpResult object for details) - */ - std::future deleteRequest(const std::string &url) noexcept { + this->url += "?" + queryString; + } - return request(url, "DELETE", "", false, {}); + return *this; } /** - * @brief Makes an HTTP DELETE request for the given URL and returns the result + * @brief Set the payload for the request + * You can send form data like param1=7¶m2=test or JSON data like {"param1": 7, "param2": "test"} + * You need to send the "Content-Type" as "application/json" in the HTTP Header, if you need to send json data in the payload * - * @param url: Request URL * @param payload: Payload to be sent with the request - * @return Result of the request (see HttpResult object for details) */ - std::future deleteRequest(const std::string &url, const std::string &payload) noexcept { + HttpClient &setPayload(const std::string &payload) { - return request(url, "DELETE", payload, false, {}); - } + this->payload = payload; - /** - * @brief Makes an HTTP DELETE request for the given URL and returns the result - * - * @param url: Request URL - * @param returnAsBinary: Return result as binary instead of string - * @return Result of the request (see HttpResult object for details) - */ - std::future deleteRequest(const std::string &url, bool returnAsBinary) noexcept { - - return request(url, "DELETE", "", returnAsBinary, {}); + return *this; } /** - * @brief Makes an HTTP DELETE request for the given URL and returns the result - * - * @param url: Request URL - * @param headers: HTTP Header information to be sent when making the request - * @return Result of the request (see HttpResult object for details) + * @brief Set the return format for the request as binary */ - std::future deleteRequest(const std::string &url, const std::map &headers) noexcept { + HttpClient &returnAsBinary() { - return request(url, "DELETE", "", false, headers); - } - - /** - * @brief Makes an HTTP DELETE request for the given URL and returns the result - * - * @param url: Request URL - * @param payload: Payload to be sent with the request - * @param returnAsBinary: Return result as binary instead of string - * @return Result of the request (see HttpResult object for details) - */ - std::future deleteRequest(const std::string &url, const std::string &payload, bool returnAsBinary) noexcept { - - return request(url, "DELETE", payload, returnAsBinary, {}); - } - - /** - * @brief Makes an HTTP DELETE request for the given URL and returns the result - * - * @param url: Request URL - * @param payload: Payload to be sent with the request - * @param headers: HTTP Header information to be sent when making the request - * @return Result of the request (see HttpResult object for details) - */ - std::future deleteRequest(const std::string &url, const std::string &payload, const std::map &headers) noexcept { + this->returnFormat = ReturnFormat::BINARY; - return request(url, "DELETE", payload, false, headers); + return *this; } /** - * @brief Makes an HTTP DELETE request for the given URL and returns the result - * - * @param url: Request URL - * @param returnAsBinary: Return result as binary instead of string - * @param headers: HTTP Header information to be sent when making the request - * @return Result of the request (see HttpResult object for details) + * @brief Ignore SSL errors when making HTTP requests */ - std::future deleteRequest(const std::string &url, bool returnAsBinary, const std::map &headers) noexcept { + HttpClient &ignoreSslErrors() { - return request(url, "DELETE", "", returnAsBinary, headers); - } + this->sslErrorsWillBeIgnored = true; - /** - * @brief Makes an HTTP DELETE request for the given URL and returns the result - * - * @param url: Request URL - * @param payload: Payload to be sent with the request - * @param returnAsBinary: Return result as binary instead of string - * @param headers: HTTP Header information to be sent when making the request - * @return Result of the request (see HttpResult object for details) - */ - std::future deleteRequest(const std::string &url, const std::string &payload, bool returnAsBinary, const std::map &headers) noexcept { - - return request(url, "DELETE", payload, returnAsBinary, headers); + return *this; } - /** - * @brief Makes an HTTP PATCH request for the given URL and returns the result + * @brief Add a HTTP header to the request * - * @param url: Request URL - * @return Result of the request (see HttpResult object for details) + * @param key: Header key + * @param value: Header value */ - std::future patchRequest(const std::string &url) noexcept { + HttpClient &addHeader(const std::string &key, const std::string &value) { - return request(url, "PATCH", "", false, {}); - } + this->headers[key] = value; - /** - * @brief Makes an HTTP PATCH request for the given URL and returns the result - * - * @param url: Request URL - * @param returnAsBinary: Return result as binary instead of string - * @return Result of the request (see HttpResult object for details) - */ - std::future patchRequest(const std::string &url, bool returnAsBinary) noexcept { - - return request(url, "PATCH", "", returnAsBinary, {}); + return *this; } /** - * @brief Makes an HTTP PATCH request for the given URL and returns the result + * @brief Send the HTTP request and return the result as a future + * The result can be obtained by calling the get() method of the future + * get() method will block until the result is available so it is recommended to use it + * when you need the result and no more other http requests will be made as parallel * - * @param url: Request URL - * @param headers: HTTP Header information to be sent when making the request - * @return Result of the request (see HttpResult object for details) + * @return Result of the request as a future (see HttpResult object for details) */ - std::future patchRequest(const std::string &url, const std::map &headers) noexcept { + std::future send() noexcept { - return request(url, "PATCH", "", false, headers); + return this->sendRequest(); } - /** - * @brief Makes an HTTP PATCH request for the given URL and returns the result - * - * @param url: Request URL - * @param returnAsBinary: Return result as binary instead of string - * @param headers: HTTP Header information to be sent when making the request - * @return Result of the request (see HttpResult object for details) - */ - std::future patchRequest(const std::string &url, bool returnAsBinary, const std::map &headers) noexcept { + private: - return request(url, "PATCH", "", returnAsBinary, headers); - } + enum class ReturnFormat { + TEXT, + BINARY + }; - private: + std::string url; + std::string method = "GET"; + std::string payload; + bool sslErrorsWillBeIgnored = false; + ReturnFormat returnFormat = ReturnFormat::TEXT; + std::map headers; struct CurlDeleter { @@ -520,9 +252,9 @@ namespace lklibs { } }; - std::future request(const std::string &url, const std::string &method, const std::string &payload, bool returnAsBinary, const std::map &headers) { + std::future sendRequest() noexcept { - return std::async(std::launch::async, [this, url, method, payload, returnAsBinary, headers]() -> HttpResult { + return std::async(std::launch::async, [this]() -> HttpResult { std::unique_ptr curl(curl_easy_init()); @@ -533,7 +265,7 @@ namespace lklibs { std::unique_ptr headerList(nullptr); - for (const auto &header: headers) { + for (const auto &header: this->headers) { std::string headerStr = header.first + ": " + header.second; @@ -545,17 +277,17 @@ namespace lklibs { int statusCode = 0; curl_easy_setopt(curl.get(), CURLOPT_HTTPHEADER, headerList.get()); - curl_easy_setopt(curl.get(), CURLOPT_URL, url.c_str()); - curl_easy_setopt(curl.get(), CURLOPT_CUSTOMREQUEST, method.c_str()); - curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYPEER, this->ignoreSslErrors ? 0L : 1L); - curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYHOST, this->ignoreSslErrors ? 0L : 1L); + curl_easy_setopt(curl.get(), CURLOPT_URL, this->url.c_str()); + curl_easy_setopt(curl.get(), CURLOPT_CUSTOMREQUEST, this->method.c_str()); + curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYPEER, this->sslErrorsWillBeIgnored ? 0L : 1L); + curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYHOST, this->sslErrorsWillBeIgnored ? 0L : 1L); - if (!payload.empty()) { + if (!this->payload.empty()) { - curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDS, payload.c_str()); + curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDS, this->payload.c_str()); } - if (returnAsBinary) { + if (this->returnFormat == ReturnFormat::BINARY) { curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, binaryWriteCallback); curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &binaryBuffer); diff --git a/test/test.cpp b/test/test.cpp index bbc9823..46468de 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -7,9 +7,12 @@ using json = nlohmann::json; TEST(HttpGetTest, HttpGetRequestMustBeCompletedSuccessfullyInItsSimplestForm) { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/get"); - auto response = httpClient.getRequest("https://httpbun.com/get?param1=7¶m2=test").get(); + auto response = httpClient + .setQueryString("param1=7¶m2=test") + .send() + .get(); ASSERT_TRUE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 200) << "HTTP Status Code is not 200"; @@ -26,11 +29,13 @@ TEST(HttpGetTest, HttpGetRequestMustBeCompletedSuccessfullyInItsSimplestForm) { TEST(HttpGetTest, MultipleHttpGetRequestMustBeCompletedSuccessfullyInNonBlockingForm) { - HttpClient httpClient; + HttpClient httpClient1("https://httpbun.com/get"); + HttpClient httpClient2("https://httpbun.com/get"); + HttpClient httpClient3("https://httpbun.com/get"); - auto future1 = httpClient.getRequest("https://httpbun.com/get?param1=1¶m2=test1"); - auto future2 = httpClient.getRequest("https://httpbun.com/get?param1=2¶m2=test2"); - auto future3 = httpClient.getRequest("https://httpbun.com/get?param1=3¶m2=test3"); + auto future1 = httpClient1.setQueryString("param1=1¶m2=test1").send(); + auto future2 = httpClient2.setQueryString("param1=2¶m2=test2").send(); + auto future3 = httpClient3.setQueryString("param1=3¶m2=test3").send(); auto response1 = future1.get(); auto response2 = future2.get(); @@ -73,9 +78,12 @@ TEST(HttpGetTest, MultipleHttpGetRequestMustBeCompletedSuccessfullyInNonBlocking TEST(HttpGetTest, ResponseOfAnHttpGetRequestCanBeReceivedInBinaryFormat) { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/bytes/100"); - auto response = httpClient.getRequest("https://httpbun.com/bytes/100", true).get(); + auto response = httpClient + .returnAsBinary() + .send() + .get(); ASSERT_TRUE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 200) << "HTTP Status Code is not 200"; @@ -86,9 +94,9 @@ TEST(HttpGetTest, ResponseOfAnHttpGetRequestCanBeReceivedInBinaryFormat) { TEST(HttpGetTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpGetRequestMadeToAnInvalidAddress) { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/not_found"); - auto response = httpClient.getRequest("https://httpbun.com/not_found").get(); + auto response = httpClient.send().get(); ASSERT_FALSE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 404) << "HTTP Status Code is not 404"; @@ -97,9 +105,9 @@ TEST(HttpGetTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpGetRequestMade TEST(HttpGetTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpGetRequestForAnotherError) { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/bearer"); - auto response = httpClient.getRequest("https://httpbun.com/bearer").get(); + auto response = httpClient.send().get(); ASSERT_FALSE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 401) << "HTTP Status Code is not 401"; @@ -108,14 +116,14 @@ TEST(HttpGetTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpGetRequestForA TEST(HttpGetTest, HttpHeadersCanBeSentWithTheHttpGetRequest) { - auto headers = std::map(); + HttpClient httpClient("https://httpbun.com/get"); - headers["Custom-Header1"] = "value1"; - headers["Custom-Header2"] = "value2"; - - HttpClient httpClient; - - auto response = httpClient.getRequest("https://httpbun.com/get?param1=7¶m2=test", headers).get(); + auto response = httpClient + .setQueryString("param1=7¶m2=test") + .addHeader("Custom-Header1", "value1") + .addHeader("Custom-Header2", "value2") + .send() + .get(); ASSERT_TRUE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 200) << "HTTP Status Code is not 200"; @@ -135,11 +143,13 @@ TEST(HttpGetTest, HttpHeadersCanBeSentWithTheHttpGetRequest) { TEST(HttpPostTest, HttpPostRequestMustBeCompletedSuccessfullyInItsSimplestForm) { - std::string payload = "param1=7¶m2=test"; - - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/post"); - auto response = httpClient.postRequest("https://httpbun.com/post", payload).get(); + auto response = httpClient + .setMethod(HttpMethod::POST) + .setPayload("param1=7¶m2=test") + .send() + .get(); ASSERT_TRUE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 200) << "HTTP Status Code is not 200"; @@ -156,15 +166,13 @@ TEST(HttpPostTest, HttpPostRequestMustBeCompletedSuccessfullyInItsSimplestForm) TEST(HttpPostTest, MultipleHttpPostRequestMustBeCompletedSuccessfullyInNonBlockingForm) { - std::string payload1 = "param1=1¶m2=test1"; - std::string payload2 = "param1=2¶m2=test2"; - std::string payload3 = "param1=3¶m2=test3"; + HttpClient httpClient1("https://httpbun.com/post"); + HttpClient httpClient2("https://httpbun.com/post"); + HttpClient httpClient3("https://httpbun.com/post"); - HttpClient httpClient; - - auto future1 = httpClient.postRequest("https://httpbun.com/post", payload1); - auto future2 = httpClient.postRequest("https://httpbun.com/post", payload2); - auto future3 = httpClient.postRequest("https://httpbun.com/post", payload3); + auto future1 = httpClient1.setMethod(HttpMethod::POST).setPayload("param1=1¶m2=test1").send(); + auto future2 = httpClient2.setMethod(HttpMethod::POST).setPayload("param1=2¶m2=test2").send(); + auto future3 = httpClient3.setMethod(HttpMethod::POST).setPayload("param1=3¶m2=test3").send(); auto response1 = future1.get(); auto response2 = future2.get(); @@ -207,9 +215,13 @@ TEST(HttpPostTest, MultipleHttpPostRequestMustBeCompletedSuccessfullyInNonBlocki TEST(HttpPostTest, ResponseOfAnHttpPostRequestCanBeReceivedInBinaryFormat) { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/bytes/100"); - auto response = httpClient.postRequest("https://httpbun.com/bytes/100", true).get(); + auto response = httpClient + .setMethod(HttpMethod::POST) + .returnAsBinary() + .send() + .get(); ASSERT_TRUE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 200) << "HTTP Status Code is not 200"; @@ -220,9 +232,12 @@ TEST(HttpPostTest, ResponseOfAnHttpPostRequestCanBeReceivedInBinaryFormat) { TEST(HttpPostTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPostRequestMadeToAnInvalidAddress) { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/not_found"); - auto response = httpClient.postRequest("https://httpbun.com/not_found").get(); + auto response = httpClient + .setMethod(HttpMethod::POST) + .send() + .get(); ASSERT_FALSE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 404) << "HTTP Status Code is not 404"; @@ -231,9 +246,12 @@ TEST(HttpPostTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPostRequestMa TEST(HttpPostTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPostRequestForAnotherError) { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/bearer"); - auto response = httpClient.postRequest("https://httpbun.com/bearer").get(); + auto response = httpClient + .setMethod(HttpMethod::POST) + .send() + .get(); ASSERT_FALSE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 401) << "HTTP Status Code is not 401"; @@ -242,17 +260,16 @@ TEST(HttpPostTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPostRequestFo TEST(HttpPostTest, HttpHeadersCanBeSentWithTheHttpPostRequest) { - std::string payload = R"({"param1": 7, "param2": "test"})"; - - auto headers = std::map(); - - headers["Content-Type"] = "application/json"; - headers["Custom-Header1"] = "value1"; - headers["Custom-Header2"] = "value2"; + HttpClient httpClient("https://httpbun.com/post"); - HttpClient httpClient; - - auto response = httpClient.postRequest("https://httpbun.com/post", payload, headers).get(); + auto response = httpClient + .setMethod(HttpMethod::POST) + .setPayload(R"({"param1": 7, "param2": "test"})") + .addHeader("Content-Type", "application/json") + .addHeader("Custom-Header1", "value1") + .addHeader("Custom-Header2", "value2") + .send() + .get(); ASSERT_TRUE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 200) << "HTTP Status Code is not 200"; @@ -273,11 +290,13 @@ TEST(HttpPostTest, HttpHeadersCanBeSentWithTheHttpPostRequest) { TEST(HttpPutTest, HttpPutRequestMustBeCompletedSuccessfullyInItsSimplestForm) { - std::string payload = "param1=7¶m2=test"; - - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/put"); - auto response = httpClient.putRequest("https://httpbun.com/put", payload).get(); + auto response = httpClient + .setMethod(HttpMethod::PUT) + .setPayload("param1=7¶m2=test") + .send() + .get(); ASSERT_TRUE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 200) << "HTTP Status Code is not 200"; @@ -294,15 +313,13 @@ TEST(HttpPutTest, HttpPutRequestMustBeCompletedSuccessfullyInItsSimplestForm) { TEST(HttpPutTest, MultipleHttpPutRequestMustBeCompletedSuccessfullyInNonBlockingForm) { - std::string payload1 = "param1=1¶m2=test1"; - std::string payload2 = "param1=2¶m2=test2"; - std::string payload3 = "param1=3¶m2=test3"; - - HttpClient httpClient; + HttpClient httpClient1("https://httpbun.com/put"); + HttpClient httpClient2("https://httpbun.com/put"); + HttpClient httpClient3("https://httpbun.com/put"); - auto future1 = httpClient.putRequest("https://httpbun.com/put", payload1); - auto future2 = httpClient.putRequest("https://httpbun.com/put", payload2); - auto future3 = httpClient.putRequest("https://httpbun.com/put", payload3); + auto future1 = httpClient1.setMethod(HttpMethod::PUT).setPayload("param1=1¶m2=test1").send(); + auto future2 = httpClient2.setMethod(HttpMethod::PUT).setPayload("param1=2¶m2=test2").send(); + auto future3 = httpClient3.setMethod(HttpMethod::PUT).setPayload("param1=3¶m2=test3").send(); auto response1 = future1.get(); auto response2 = future2.get(); @@ -345,9 +362,13 @@ TEST(HttpPutTest, MultipleHttpPutRequestMustBeCompletedSuccessfullyInNonBlocking TEST(HttpPutTest, ResponseOfAnHttpPutRequestCanBeReceivedInBinaryFormat) { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/bytes/100"); - auto response = httpClient.putRequest("https://httpbun.com/bytes/100", true).get(); + auto response = httpClient + .setMethod(HttpMethod::PUT) + .returnAsBinary() + .send() + .get(); ASSERT_TRUE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 200) << "HTTP Status Code is not 200"; @@ -358,9 +379,12 @@ TEST(HttpPutTest, ResponseOfAnHttpPutRequestCanBeReceivedInBinaryFormat) { TEST(HttpPutTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPutRequestMadeToAnInvalidAddress) { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/not_found"); - auto response = httpClient.putRequest("https://httpbun.com/not_found").get(); + auto response = httpClient + .setMethod(HttpMethod::PUT) + .send() + .get(); ASSERT_FALSE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 404) << "HTTP Status Code is not 404"; @@ -369,9 +393,12 @@ TEST(HttpPutTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPutRequestMade TEST(HttpPutTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPutRequestForAnotherError) { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/bearer"); - auto response = httpClient.putRequest("https://httpbun.com/bearer").get(); + auto response = httpClient + .setMethod(HttpMethod::PUT) + .send() + .get(); ASSERT_FALSE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 401) << "HTTP Status Code is not 401"; @@ -380,17 +407,16 @@ TEST(HttpPutTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPutRequestForA TEST(HttpPutTest, HttpHeadersCanBeSentWithTheHttpPutRequest) { - std::string payload = R"({"param1": 7, "param2": "test"})"; - - auto headers = std::map(); - - headers["Content-Type"] = "application/json"; - headers["Custom-Header1"] = "value1"; - headers["Custom-Header2"] = "value2"; + HttpClient httpClient("https://httpbun.com/put"); - HttpClient httpClient; - - auto response = httpClient.putRequest("https://httpbun.com/put", payload, headers).get(); + auto response = httpClient + .setMethod(HttpMethod::PUT) + .setPayload(R"({"param1": 7, "param2": "test"})") + .addHeader("Content-Type", "application/json") + .addHeader("Custom-Header1", "value1") + .addHeader("Custom-Header2", "value2") + .send() + .get(); ASSERT_TRUE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 200) << "HTTP Status Code is not 200"; @@ -411,11 +437,13 @@ TEST(HttpPutTest, HttpHeadersCanBeSentWithTheHttpPutRequest) { TEST(HttpDeleteTest, HttpDeleteRequestMustBeCompletedSuccessfullyInItsSimplestForm) { - std::string payload = "param1=7¶m2=test"; - - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/delete"); - auto response = httpClient.deleteRequest("https://httpbun.com/delete", payload).get(); + auto response = httpClient + .setMethod(HttpMethod::DELETE_) + .setPayload("param1=7¶m2=test") + .send() + .get(); ASSERT_TRUE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 200) << "HTTP Status Code is not 200"; @@ -432,15 +460,13 @@ TEST(HttpDeleteTest, HttpDeleteRequestMustBeCompletedSuccessfullyInItsSimplestFo TEST(HttpDeleteTest, MultipleHttpDeleteRequestMustBeCompletedSuccessfullyInNonBlockingForm) { - std::string payload1 = "param1=1¶m2=test1"; - std::string payload2 = "param1=2¶m2=test2"; - std::string payload3 = "param1=3¶m2=test3"; - - HttpClient httpClient; + HttpClient httpClient1("https://httpbun.com/delete"); + HttpClient httpClient2("https://httpbun.com/delete"); + HttpClient httpClient3("https://httpbun.com/delete"); - auto future1 = httpClient.deleteRequest("https://httpbun.com/delete", payload1); - auto future2 = httpClient.deleteRequest("https://httpbun.com/delete", payload2); - auto future3 = httpClient.deleteRequest("https://httpbun.com/delete", payload3); + auto future1 = httpClient1.setMethod(HttpMethod::DELETE_).setPayload("param1=1¶m2=test1").send(); + auto future2 = httpClient2.setMethod(HttpMethod::DELETE_).setPayload("param1=2¶m2=test2").send(); + auto future3 = httpClient3.setMethod(HttpMethod::DELETE_).setPayload("param1=3¶m2=test3").send(); auto response1 = future1.get(); auto response2 = future2.get(); @@ -483,9 +509,13 @@ TEST(HttpDeleteTest, MultipleHttpDeleteRequestMustBeCompletedSuccessfullyInNonBl TEST(HttpDeleteTest, ResponseOfAnHttpDeleteRequestCanBeReceivedInBinaryFormat) { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/bytes/100"); - auto response = httpClient.deleteRequest("https://httpbun.com/bytes/100", true).get(); + auto response = httpClient + .setMethod(HttpMethod::DELETE_) + .returnAsBinary() + .send() + .get(); ASSERT_TRUE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 200) << "HTTP Status Code is not 200"; @@ -496,9 +526,12 @@ TEST(HttpDeleteTest, ResponseOfAnHttpDeleteRequestCanBeReceivedInBinaryFormat) { TEST(HttpDeleteTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpDeleteRequestMadeToAnInvalidAddress) { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/not_found"); - auto response = httpClient.deleteRequest("https://httpbun.com/not_found").get(); + auto response = httpClient + .setMethod(HttpMethod::DELETE_) + .send() + .get(); ASSERT_FALSE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 404) << "HTTP Status Code is not 404"; @@ -507,9 +540,12 @@ TEST(HttpDeleteTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpDeleteReque TEST(HttpDeleteTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpDeleteRequestForAnotherError) { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/bearer"); - auto response = httpClient.deleteRequest("https://httpbun.com/bearer").get(); + auto response = httpClient + .setMethod(HttpMethod::DELETE_) + .send() + .get(); ASSERT_FALSE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 401) << "HTTP Status Code is not 401"; @@ -518,17 +554,16 @@ TEST(HttpDeleteTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpDeleteReque TEST(HttpDeleteTest, HttpHeadersCanBeSentWithTheHttpDeleteRequest) { - std::string payload = R"({"param1": 7, "param2": "test"})"; - - auto headers = std::map(); - - headers["Content-Type"] = "application/json"; - headers["Custom-Header1"] = "value1"; - headers["Custom-Header2"] = "value2"; - - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/delete"); - auto response = httpClient.deleteRequest("https://httpbun.com/delete", payload, headers).get(); + auto response = httpClient + .setMethod(HttpMethod::DELETE_) + .setPayload(R"({"param1": 7, "param2": "test"})") + .addHeader("Content-Type", "application/json") + .addHeader("Custom-Header1", "value1") + .addHeader("Custom-Header2", "value2") + .send() + .get(); ASSERT_TRUE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 200) << "HTTP Status Code is not 200"; @@ -547,11 +582,16 @@ TEST(HttpDeleteTest, HttpHeadersCanBeSentWithTheHttpDeleteRequest) { ASSERT_EQ(data["headers"]["Custom-Header2"], "value2") << "Custom-Header2 is invalid"; } + TEST(HttpPatchTest, HttpPatchRequestMustBeCompletedSuccessfullyInItsSimplestForm) { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/patch"); - auto response = httpClient.patchRequest("https://httpbun.com/patch?param1=7¶m2=test").get(); + auto response = httpClient + .setMethod(HttpMethod::PATCH) + .setQueryString("param1=7¶m2=test") + .send() + .get(); ASSERT_TRUE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 200) << "HTTP Status Code is not 200"; @@ -568,11 +608,13 @@ TEST(HttpPatchTest, HttpPatchRequestMustBeCompletedSuccessfullyInItsSimplestForm TEST(HttpPatchTest, MultipleHttpPatchRequestMustBeCompletedSuccessfullyInNonBlockingForm) { - HttpClient httpClient; + HttpClient httpClient1("https://httpbun.com/patch"); + HttpClient httpClient2("https://httpbun.com/patch"); + HttpClient httpClient3("https://httpbun.com/patch"); - auto future1 = httpClient.patchRequest("https://httpbun.com/patch?param1=1¶m2=test1"); - auto future2 = httpClient.patchRequest("https://httpbun.com/patch?param1=2¶m2=test2"); - auto future3 = httpClient.patchRequest("https://httpbun.com/patch?param1=3¶m2=test3"); + auto future1 = httpClient1.setMethod(HttpMethod::PATCH).setQueryString("param1=1¶m2=test1").send(); + auto future2 = httpClient2.setMethod(HttpMethod::PATCH).setQueryString("param1=2¶m2=test2").send(); + auto future3 = httpClient3.setMethod(HttpMethod::PATCH).setQueryString("param1=3¶m2=test3").send(); auto response1 = future1.get(); auto response2 = future2.get(); @@ -615,9 +657,13 @@ TEST(HttpPatchTest, MultipleHttpPatchRequestMustBeCompletedSuccessfullyInNonBloc TEST(HttpPatchTest, ResponseOfAnHttpPatchRequestCanBeReceivedInBinaryFormat) { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/bytes/100"); - auto response = httpClient.patchRequest("https://httpbun.com/bytes/100", true).get(); + auto response = httpClient + .setMethod(HttpMethod::PATCH) + .returnAsBinary() + .send() + .get(); ASSERT_TRUE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 200) << "HTTP Status Code is not 200"; @@ -628,9 +674,9 @@ TEST(HttpPatchTest, ResponseOfAnHttpPatchRequestCanBeReceivedInBinaryFormat) { TEST(HttpPatchTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPatchRequestMadeToAnInvalidAddress) { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/not_found"); - auto response = httpClient.patchRequest("https://httpbun.com/not_found").get(); + auto response = httpClient.setMethod(HttpMethod::PATCH).send().get(); ASSERT_FALSE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 404) << "HTTP Status Code is not 404"; @@ -639,9 +685,9 @@ TEST(HttpPatchTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPatchRequest TEST(HttpPatchTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPatchRequestForAnotherError) { - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/bearer"); - auto response = httpClient.patchRequest("https://httpbun.com/bearer").get(); + auto response = httpClient.setMethod(HttpMethod::PATCH).send().get(); ASSERT_FALSE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 401) << "HTTP Status Code is not 401"; @@ -650,15 +696,15 @@ TEST(HttpPatchTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPatchRequest TEST(HttpPatchTest, HttpHeadersCanBeSentWithTheHttpPatchRequest) { - auto headers = std::map(); - - headers["Content-Type"] = "application/json"; - headers["Custom-Header1"] = "value1"; - headers["Custom-Header2"] = "value2"; - - HttpClient httpClient; + HttpClient httpClient("https://httpbun.com/patch"); - auto response = httpClient.patchRequest("https://httpbun.com/patch?param1=7¶m2=test", headers).get(); + auto response = httpClient + .setMethod(HttpMethod::PATCH) + .setQueryString("param1=7¶m2=test") + .addHeader("Custom-Header1", "value1") + .addHeader("Custom-Header2", "value2") + .send() + .get(); ASSERT_TRUE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 200) << "HTTP Status Code is not 200"; @@ -672,16 +718,15 @@ TEST(HttpPatchTest, HttpHeadersCanBeSentWithTheHttpPatchRequest) { ASSERT_EQ(data["args"]["param1"], "7") << "Querystring is invalid"; ASSERT_EQ(data["args"]["param2"], "test") << "Querystring is invalid"; - ASSERT_EQ(data["headers"]["Content-Type"], "application/json") << "Content-Type is invalid"; ASSERT_EQ(data["headers"]["Custom-Header1"], "value1") << "Custom-Header1 is invalid"; ASSERT_EQ(data["headers"]["Custom-Header2"], "value2") << "Custom-Header2 is invalid"; } TEST(InvalidSSLTest, HttpGetRequestMustReturnErrorForAnInvalidSsl) { - HttpClient httpClient; + HttpClient httpClient("https://self-signed-cert.httpbun.com"); - auto response = httpClient.getRequest("https://self-signed-cert.httpbun.com").get(); + auto response = httpClient.send().get(); ASSERT_FALSE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 0) << "HTTP Status Code is not 0"; @@ -690,11 +735,9 @@ TEST(InvalidSSLTest, HttpGetRequestMustReturnErrorForAnInvalidSsl) { TEST(InvalidSSLTest, HttpGetRequestMustBeCompletedSuccessfullyForAnInvalidSslIfIgnoreSslErrorsFieldSetTrue) { - HttpClient httpClient; - - httpClient.ignoreSslErrors = true; + HttpClient httpClient("https://self-signed-cert.httpbun.com"); - auto response = httpClient.getRequest("https://self-signed-cert.httpbun.com").get(); + auto response = httpClient.ignoreSslErrors().send().get(); ASSERT_TRUE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 200) << "HTTP Status Code is not 200"; From b29eb43ee7cf458320a619c19e3b8af9b6247957 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Levent=20KARAG=C3=96L?= Date: Sun, 21 Apr 2024 14:23:20 +0300 Subject: [PATCH 2/7] Method overloading structure converted to Builder Pattern --- examples/main.cpp | 52 ++++++------ src/libcpp-http-client.hpp | 22 ++--- test/test.cpp | 168 ++++++++++++++++++------------------- 3 files changed, 121 insertions(+), 121 deletions(-) diff --git a/examples/main.cpp b/examples/main.cpp index 93ec58f..51544bb 100644 --- a/examples/main.cpp +++ b/examples/main.cpp @@ -5,10 +5,10 @@ using namespace lklibs; void simpleGet() { - HttpClient httpClient("https://httpbun.com/get"); + HttpRequest httpRequest("https://httpbun.com/get"); // The simplest but slowest method if multiple calls will be made - auto response = httpClient + auto response = httpRequest .setQueryString("param1=7¶m2=test") .send() .get(); @@ -20,14 +20,14 @@ void simpleGet() { void nonBlockingGet() { - HttpClient httpClient1("https://httpbun.com/get"); - HttpClient httpClient2("https://httpbun.com/get"); - HttpClient httpClient3("https://httpbun.com/get"); + HttpRequest httpRequest1("https://httpbun.com/get"); + HttpRequest httpRequest2("https://httpbun.com/get"); + HttpRequest httpRequest3("https://httpbun.com/get"); // All requests are made one after the other without waiting for a response - auto future1 = httpClient1.setQueryString("param1=1¶m2=test1").send(); - auto future2 = httpClient2.setQueryString("param1=2¶m2=test2").send(); - auto future3 = httpClient3.setQueryString("param1=3¶m2=test3").send(); + auto future1 = httpRequest1.setQueryString("param1=1¶m2=test1").send(); + auto future2 = httpRequest2.setQueryString("param1=2¶m2=test2").send(); + auto future3 = httpRequest3.setQueryString("param1=3¶m2=test3").send(); // Then all the answers are received. Thus, 3 requests are sent in parallel auto response1 = future1.get(); @@ -49,10 +49,10 @@ void nonBlockingGet() { void receiveBinaryData() { - HttpClient httpClient("https://httpbun.com/bytes/100"); + HttpRequest httpRequest("https://httpbun.com/bytes/100"); // If you need to retrieve binary data such as an image, just call the "returnAsBinary" method - auto response = httpClient + auto response = httpRequest .returnAsBinary() .send() .get(); @@ -66,10 +66,10 @@ void receiveBinaryData() { void receiveError() { - HttpClient httpClient("https://httpbun.com/not_found"); + HttpRequest httpRequest("https://httpbun.com/not_found"); // This is an exception free library. If an error occurs, no exception is thrown - auto response = httpClient.send().get(); + auto response = httpRequest.send().get(); // Instead, the succeed field of the response object is set to false std::cout << "Succeed: " << response.succeed << std::endl; @@ -83,10 +83,10 @@ void receiveError() { void sendingHttpHeaders() { - HttpClient httpClient("https://httpbun.com/get?param1=7¶m2=test"); + HttpRequest httpRequest("https://httpbun.com/get?param1=7¶m2=test"); // You can send custom headers as key-value pairs - auto response = httpClient + auto response = httpRequest .addHeader("Custom-Header1", "value1") .addHeader("Custom-Header2", "value2") .send() @@ -97,10 +97,10 @@ void sendingHttpHeaders() { void simplePostWithFormData() { - HttpClient httpClient("https://httpbun.com/post"); + HttpRequest httpRequest("https://httpbun.com/post"); // You can send a POST request with form data in the payload - auto response = httpClient + auto response = httpRequest .setMethod(HttpMethod::POST) .setPayload("param1=7¶m2=test") .send() @@ -113,10 +113,10 @@ void simplePostWithFormData() { void simplePostWithJSONData() { - HttpClient httpClient("https://httpbun.com/post"); + HttpRequest httpRequest("https://httpbun.com/post"); // You need to send the "Content-Type" as "application/json" in the HTTP Header, if you need to send json data in the payload - auto response = httpClient + auto response = httpRequest .setMethod(HttpMethod::POST) .setPayload(R"({"param1": 7, "param2": "test"})") .addHeader("Content-Type", "application/json") @@ -130,10 +130,10 @@ void simplePostWithJSONData() { void simplePutWithFormData() { - HttpClient httpClient("https://httpbun.com/put"); + HttpRequest httpRequest("https://httpbun.com/put"); // You can send a PUT request with form data in the payload just like POST - auto response = httpClient + auto response = httpRequest .setMethod(HttpMethod::PUT) .setPayload("param1=7¶m2=test") .send() @@ -146,10 +146,10 @@ void simplePutWithFormData() { void simpleDeleteWithFormData() { - HttpClient httpClient("https://httpbun.com/delete"); + HttpRequest httpRequest("https://httpbun.com/delete"); // You can send a DELETE request with form data in the payload just like POST - auto response = httpClient + auto response = httpRequest .setMethod(HttpMethod::DELETE_) .setPayload("param1=7¶m2=test") .send() @@ -162,10 +162,10 @@ void simpleDeleteWithFormData() { void simplePatch() { - HttpClient httpClient("https://httpbun.com/patch"); + HttpRequest httpRequest("https://httpbun.com/patch"); // You can send a PATCH request with QueryString just like GET - auto response = httpClient + auto response = httpRequest .setMethod(HttpMethod::PATCH) .setQueryString("param1=7¶m2=test") .send() @@ -178,10 +178,10 @@ void simplePatch() { void ignoreSslErrors() { - HttpClient httpClient("https://self-signed-cert.httpbun.com"); + HttpRequest httpRequest("https://self-signed-cert.httpbun.com"); // If you need to ignore SSL errors, you can call "ignoreSslErrors" method before sending the request - auto response = httpClient.ignoreSslErrors().send().get(); + auto response = httpRequest.ignoreSslErrors().send().get(); std::cout << "Succeed: " << response.succeed << std::endl; std::cout << "Http Status Code: " << response.statusCode << std::endl; diff --git a/src/libcpp-http-client.hpp b/src/libcpp-http-client.hpp index 5496181..18d6fd0 100644 --- a/src/libcpp-http-client.hpp +++ b/src/libcpp-http-client.hpp @@ -89,24 +89,24 @@ namespace lklibs { }; /** - * @brief HTTP client class that makes asynchronous HTTP requests + * @brief HTTP request class that makes asynchronous HTTP calls */ - class HttpClient { + class HttpRequest { public: /** - * @brief Constructor for the HttpClient class + * @brief Constructor for the HttpRequest class * * @param url: URL for the request */ - explicit HttpClient(const std::string &url) { + explicit HttpRequest(const std::string &url) { this->url = url; curl_global_init(CURL_GLOBAL_DEFAULT); } - ~HttpClient() { + ~HttpRequest() { curl_global_cleanup(); } @@ -115,7 +115,7 @@ namespace lklibs { * * @param method: HTTP method to be used for the request */ - HttpClient &setMethod(const HttpMethod &method) { + HttpRequest &setMethod(const HttpMethod &method) { this->method = [method] { switch (method) { @@ -142,7 +142,7 @@ namespace lklibs { * * @param queryString: Query string to be sent with the request */ - HttpClient &setQueryString(const std::string &queryString) { + HttpRequest &setQueryString(const std::string &queryString) { if (this->url.find('?') != std::string::npos) { @@ -163,7 +163,7 @@ namespace lklibs { * * @param payload: Payload to be sent with the request */ - HttpClient &setPayload(const std::string &payload) { + HttpRequest &setPayload(const std::string &payload) { this->payload = payload; @@ -173,7 +173,7 @@ namespace lklibs { /** * @brief Set the return format for the request as binary */ - HttpClient &returnAsBinary() { + HttpRequest &returnAsBinary() { this->returnFormat = ReturnFormat::BINARY; @@ -183,7 +183,7 @@ namespace lklibs { /** * @brief Ignore SSL errors when making HTTP requests */ - HttpClient &ignoreSslErrors() { + HttpRequest &ignoreSslErrors() { this->sslErrorsWillBeIgnored = true; @@ -196,7 +196,7 @@ namespace lklibs { * @param key: Header key * @param value: Header value */ - HttpClient &addHeader(const std::string &key, const std::string &value) { + HttpRequest &addHeader(const std::string &key, const std::string &value) { this->headers[key] = value; diff --git a/test/test.cpp b/test/test.cpp index 46468de..950ccfa 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -7,9 +7,9 @@ using json = nlohmann::json; TEST(HttpGetTest, HttpGetRequestMustBeCompletedSuccessfullyInItsSimplestForm) { - HttpClient httpClient("https://httpbun.com/get"); + HttpRequest httpRequest("https://httpbun.com/get"); - auto response = httpClient + auto response = httpRequest .setQueryString("param1=7¶m2=test") .send() .get(); @@ -29,13 +29,13 @@ TEST(HttpGetTest, HttpGetRequestMustBeCompletedSuccessfullyInItsSimplestForm) { TEST(HttpGetTest, MultipleHttpGetRequestMustBeCompletedSuccessfullyInNonBlockingForm) { - HttpClient httpClient1("https://httpbun.com/get"); - HttpClient httpClient2("https://httpbun.com/get"); - HttpClient httpClient3("https://httpbun.com/get"); + HttpRequest httpRequest1("https://httpbun.com/get"); + HttpRequest httpRequest2("https://httpbun.com/get"); + HttpRequest httpRequest3("https://httpbun.com/get"); - auto future1 = httpClient1.setQueryString("param1=1¶m2=test1").send(); - auto future2 = httpClient2.setQueryString("param1=2¶m2=test2").send(); - auto future3 = httpClient3.setQueryString("param1=3¶m2=test3").send(); + auto future1 = httpRequest1.setQueryString("param1=1¶m2=test1").send(); + auto future2 = httpRequest2.setQueryString("param1=2¶m2=test2").send(); + auto future3 = httpRequest3.setQueryString("param1=3¶m2=test3").send(); auto response1 = future1.get(); auto response2 = future2.get(); @@ -78,9 +78,9 @@ TEST(HttpGetTest, MultipleHttpGetRequestMustBeCompletedSuccessfullyInNonBlocking TEST(HttpGetTest, ResponseOfAnHttpGetRequestCanBeReceivedInBinaryFormat) { - HttpClient httpClient("https://httpbun.com/bytes/100"); + HttpRequest httpRequest("https://httpbun.com/bytes/100"); - auto response = httpClient + auto response = httpRequest .returnAsBinary() .send() .get(); @@ -94,9 +94,9 @@ TEST(HttpGetTest, ResponseOfAnHttpGetRequestCanBeReceivedInBinaryFormat) { TEST(HttpGetTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpGetRequestMadeToAnInvalidAddress) { - HttpClient httpClient("https://httpbun.com/not_found"); + HttpRequest httpRequest("https://httpbun.com/not_found"); - auto response = httpClient.send().get(); + auto response = httpRequest.send().get(); ASSERT_FALSE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 404) << "HTTP Status Code is not 404"; @@ -105,9 +105,9 @@ TEST(HttpGetTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpGetRequestMade TEST(HttpGetTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpGetRequestForAnotherError) { - HttpClient httpClient("https://httpbun.com/bearer"); + HttpRequest httpRequest("https://httpbun.com/bearer"); - auto response = httpClient.send().get(); + auto response = httpRequest.send().get(); ASSERT_FALSE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 401) << "HTTP Status Code is not 401"; @@ -116,9 +116,9 @@ TEST(HttpGetTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpGetRequestForA TEST(HttpGetTest, HttpHeadersCanBeSentWithTheHttpGetRequest) { - HttpClient httpClient("https://httpbun.com/get"); + HttpRequest httpRequest("https://httpbun.com/get"); - auto response = httpClient + auto response = httpRequest .setQueryString("param1=7¶m2=test") .addHeader("Custom-Header1", "value1") .addHeader("Custom-Header2", "value2") @@ -143,9 +143,9 @@ TEST(HttpGetTest, HttpHeadersCanBeSentWithTheHttpGetRequest) { TEST(HttpPostTest, HttpPostRequestMustBeCompletedSuccessfullyInItsSimplestForm) { - HttpClient httpClient("https://httpbun.com/post"); + HttpRequest httpRequest("https://httpbun.com/post"); - auto response = httpClient + auto response = httpRequest .setMethod(HttpMethod::POST) .setPayload("param1=7¶m2=test") .send() @@ -166,13 +166,13 @@ TEST(HttpPostTest, HttpPostRequestMustBeCompletedSuccessfullyInItsSimplestForm) TEST(HttpPostTest, MultipleHttpPostRequestMustBeCompletedSuccessfullyInNonBlockingForm) { - HttpClient httpClient1("https://httpbun.com/post"); - HttpClient httpClient2("https://httpbun.com/post"); - HttpClient httpClient3("https://httpbun.com/post"); + HttpRequest httpRequest1("https://httpbun.com/post"); + HttpRequest httpRequest2("https://httpbun.com/post"); + HttpRequest httpRequest3("https://httpbun.com/post"); - auto future1 = httpClient1.setMethod(HttpMethod::POST).setPayload("param1=1¶m2=test1").send(); - auto future2 = httpClient2.setMethod(HttpMethod::POST).setPayload("param1=2¶m2=test2").send(); - auto future3 = httpClient3.setMethod(HttpMethod::POST).setPayload("param1=3¶m2=test3").send(); + auto future1 = httpRequest1.setMethod(HttpMethod::POST).setPayload("param1=1¶m2=test1").send(); + auto future2 = httpRequest2.setMethod(HttpMethod::POST).setPayload("param1=2¶m2=test2").send(); + auto future3 = httpRequest3.setMethod(HttpMethod::POST).setPayload("param1=3¶m2=test3").send(); auto response1 = future1.get(); auto response2 = future2.get(); @@ -215,9 +215,9 @@ TEST(HttpPostTest, MultipleHttpPostRequestMustBeCompletedSuccessfullyInNonBlocki TEST(HttpPostTest, ResponseOfAnHttpPostRequestCanBeReceivedInBinaryFormat) { - HttpClient httpClient("https://httpbun.com/bytes/100"); + HttpRequest httpRequest("https://httpbun.com/bytes/100"); - auto response = httpClient + auto response = httpRequest .setMethod(HttpMethod::POST) .returnAsBinary() .send() @@ -232,9 +232,9 @@ TEST(HttpPostTest, ResponseOfAnHttpPostRequestCanBeReceivedInBinaryFormat) { TEST(HttpPostTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPostRequestMadeToAnInvalidAddress) { - HttpClient httpClient("https://httpbun.com/not_found"); + HttpRequest httpRequest("https://httpbun.com/not_found"); - auto response = httpClient + auto response = httpRequest .setMethod(HttpMethod::POST) .send() .get(); @@ -246,9 +246,9 @@ TEST(HttpPostTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPostRequestMa TEST(HttpPostTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPostRequestForAnotherError) { - HttpClient httpClient("https://httpbun.com/bearer"); + HttpRequest httpRequest("https://httpbun.com/bearer"); - auto response = httpClient + auto response = httpRequest .setMethod(HttpMethod::POST) .send() .get(); @@ -260,9 +260,9 @@ TEST(HttpPostTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPostRequestFo TEST(HttpPostTest, HttpHeadersCanBeSentWithTheHttpPostRequest) { - HttpClient httpClient("https://httpbun.com/post"); + HttpRequest httpRequest("https://httpbun.com/post"); - auto response = httpClient + auto response = httpRequest .setMethod(HttpMethod::POST) .setPayload(R"({"param1": 7, "param2": "test"})") .addHeader("Content-Type", "application/json") @@ -290,9 +290,9 @@ TEST(HttpPostTest, HttpHeadersCanBeSentWithTheHttpPostRequest) { TEST(HttpPutTest, HttpPutRequestMustBeCompletedSuccessfullyInItsSimplestForm) { - HttpClient httpClient("https://httpbun.com/put"); + HttpRequest httpRequest("https://httpbun.com/put"); - auto response = httpClient + auto response = httpRequest .setMethod(HttpMethod::PUT) .setPayload("param1=7¶m2=test") .send() @@ -313,13 +313,13 @@ TEST(HttpPutTest, HttpPutRequestMustBeCompletedSuccessfullyInItsSimplestForm) { TEST(HttpPutTest, MultipleHttpPutRequestMustBeCompletedSuccessfullyInNonBlockingForm) { - HttpClient httpClient1("https://httpbun.com/put"); - HttpClient httpClient2("https://httpbun.com/put"); - HttpClient httpClient3("https://httpbun.com/put"); + HttpRequest httpRequest1("https://httpbun.com/put"); + HttpRequest httpRequest2("https://httpbun.com/put"); + HttpRequest httpRequest3("https://httpbun.com/put"); - auto future1 = httpClient1.setMethod(HttpMethod::PUT).setPayload("param1=1¶m2=test1").send(); - auto future2 = httpClient2.setMethod(HttpMethod::PUT).setPayload("param1=2¶m2=test2").send(); - auto future3 = httpClient3.setMethod(HttpMethod::PUT).setPayload("param1=3¶m2=test3").send(); + auto future1 = httpRequest1.setMethod(HttpMethod::PUT).setPayload("param1=1¶m2=test1").send(); + auto future2 = httpRequest2.setMethod(HttpMethod::PUT).setPayload("param1=2¶m2=test2").send(); + auto future3 = httpRequest3.setMethod(HttpMethod::PUT).setPayload("param1=3¶m2=test3").send(); auto response1 = future1.get(); auto response2 = future2.get(); @@ -362,9 +362,9 @@ TEST(HttpPutTest, MultipleHttpPutRequestMustBeCompletedSuccessfullyInNonBlocking TEST(HttpPutTest, ResponseOfAnHttpPutRequestCanBeReceivedInBinaryFormat) { - HttpClient httpClient("https://httpbun.com/bytes/100"); + HttpRequest httpRequest("https://httpbun.com/bytes/100"); - auto response = httpClient + auto response = httpRequest .setMethod(HttpMethod::PUT) .returnAsBinary() .send() @@ -379,9 +379,9 @@ TEST(HttpPutTest, ResponseOfAnHttpPutRequestCanBeReceivedInBinaryFormat) { TEST(HttpPutTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPutRequestMadeToAnInvalidAddress) { - HttpClient httpClient("https://httpbun.com/not_found"); + HttpRequest httpRequest("https://httpbun.com/not_found"); - auto response = httpClient + auto response = httpRequest .setMethod(HttpMethod::PUT) .send() .get(); @@ -393,9 +393,9 @@ TEST(HttpPutTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPutRequestMade TEST(HttpPutTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPutRequestForAnotherError) { - HttpClient httpClient("https://httpbun.com/bearer"); + HttpRequest httpRequest("https://httpbun.com/bearer"); - auto response = httpClient + auto response = httpRequest .setMethod(HttpMethod::PUT) .send() .get(); @@ -407,9 +407,9 @@ TEST(HttpPutTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPutRequestForA TEST(HttpPutTest, HttpHeadersCanBeSentWithTheHttpPutRequest) { - HttpClient httpClient("https://httpbun.com/put"); + HttpRequest httpRequest("https://httpbun.com/put"); - auto response = httpClient + auto response = httpRequest .setMethod(HttpMethod::PUT) .setPayload(R"({"param1": 7, "param2": "test"})") .addHeader("Content-Type", "application/json") @@ -437,9 +437,9 @@ TEST(HttpPutTest, HttpHeadersCanBeSentWithTheHttpPutRequest) { TEST(HttpDeleteTest, HttpDeleteRequestMustBeCompletedSuccessfullyInItsSimplestForm) { - HttpClient httpClient("https://httpbun.com/delete"); + HttpRequest httpRequest("https://httpbun.com/delete"); - auto response = httpClient + auto response = httpRequest .setMethod(HttpMethod::DELETE_) .setPayload("param1=7¶m2=test") .send() @@ -460,13 +460,13 @@ TEST(HttpDeleteTest, HttpDeleteRequestMustBeCompletedSuccessfullyInItsSimplestFo TEST(HttpDeleteTest, MultipleHttpDeleteRequestMustBeCompletedSuccessfullyInNonBlockingForm) { - HttpClient httpClient1("https://httpbun.com/delete"); - HttpClient httpClient2("https://httpbun.com/delete"); - HttpClient httpClient3("https://httpbun.com/delete"); + HttpRequest httpRequest1("https://httpbun.com/delete"); + HttpRequest httpRequest2("https://httpbun.com/delete"); + HttpRequest httpRequest3("https://httpbun.com/delete"); - auto future1 = httpClient1.setMethod(HttpMethod::DELETE_).setPayload("param1=1¶m2=test1").send(); - auto future2 = httpClient2.setMethod(HttpMethod::DELETE_).setPayload("param1=2¶m2=test2").send(); - auto future3 = httpClient3.setMethod(HttpMethod::DELETE_).setPayload("param1=3¶m2=test3").send(); + auto future1 = httpRequest1.setMethod(HttpMethod::DELETE_).setPayload("param1=1¶m2=test1").send(); + auto future2 = httpRequest2.setMethod(HttpMethod::DELETE_).setPayload("param1=2¶m2=test2").send(); + auto future3 = httpRequest3.setMethod(HttpMethod::DELETE_).setPayload("param1=3¶m2=test3").send(); auto response1 = future1.get(); auto response2 = future2.get(); @@ -509,9 +509,9 @@ TEST(HttpDeleteTest, MultipleHttpDeleteRequestMustBeCompletedSuccessfullyInNonBl TEST(HttpDeleteTest, ResponseOfAnHttpDeleteRequestCanBeReceivedInBinaryFormat) { - HttpClient httpClient("https://httpbun.com/bytes/100"); + HttpRequest httpRequest("https://httpbun.com/bytes/100"); - auto response = httpClient + auto response = httpRequest .setMethod(HttpMethod::DELETE_) .returnAsBinary() .send() @@ -526,9 +526,9 @@ TEST(HttpDeleteTest, ResponseOfAnHttpDeleteRequestCanBeReceivedInBinaryFormat) { TEST(HttpDeleteTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpDeleteRequestMadeToAnInvalidAddress) { - HttpClient httpClient("https://httpbun.com/not_found"); + HttpRequest httpRequest("https://httpbun.com/not_found"); - auto response = httpClient + auto response = httpRequest .setMethod(HttpMethod::DELETE_) .send() .get(); @@ -540,9 +540,9 @@ TEST(HttpDeleteTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpDeleteReque TEST(HttpDeleteTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpDeleteRequestForAnotherError) { - HttpClient httpClient("https://httpbun.com/bearer"); + HttpRequest httpRequest("https://httpbun.com/bearer"); - auto response = httpClient + auto response = httpRequest .setMethod(HttpMethod::DELETE_) .send() .get(); @@ -554,9 +554,9 @@ TEST(HttpDeleteTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpDeleteReque TEST(HttpDeleteTest, HttpHeadersCanBeSentWithTheHttpDeleteRequest) { - HttpClient httpClient("https://httpbun.com/delete"); + HttpRequest httpRequest("https://httpbun.com/delete"); - auto response = httpClient + auto response = httpRequest .setMethod(HttpMethod::DELETE_) .setPayload(R"({"param1": 7, "param2": "test"})") .addHeader("Content-Type", "application/json") @@ -585,9 +585,9 @@ TEST(HttpDeleteTest, HttpHeadersCanBeSentWithTheHttpDeleteRequest) { TEST(HttpPatchTest, HttpPatchRequestMustBeCompletedSuccessfullyInItsSimplestForm) { - HttpClient httpClient("https://httpbun.com/patch"); + HttpRequest httpRequest("https://httpbun.com/patch"); - auto response = httpClient + auto response = httpRequest .setMethod(HttpMethod::PATCH) .setQueryString("param1=7¶m2=test") .send() @@ -608,13 +608,13 @@ TEST(HttpPatchTest, HttpPatchRequestMustBeCompletedSuccessfullyInItsSimplestForm TEST(HttpPatchTest, MultipleHttpPatchRequestMustBeCompletedSuccessfullyInNonBlockingForm) { - HttpClient httpClient1("https://httpbun.com/patch"); - HttpClient httpClient2("https://httpbun.com/patch"); - HttpClient httpClient3("https://httpbun.com/patch"); + HttpRequest httpRequest1("https://httpbun.com/patch"); + HttpRequest httpRequest2("https://httpbun.com/patch"); + HttpRequest httpRequest3("https://httpbun.com/patch"); - auto future1 = httpClient1.setMethod(HttpMethod::PATCH).setQueryString("param1=1¶m2=test1").send(); - auto future2 = httpClient2.setMethod(HttpMethod::PATCH).setQueryString("param1=2¶m2=test2").send(); - auto future3 = httpClient3.setMethod(HttpMethod::PATCH).setQueryString("param1=3¶m2=test3").send(); + auto future1 = httpRequest1.setMethod(HttpMethod::PATCH).setQueryString("param1=1¶m2=test1").send(); + auto future2 = httpRequest2.setMethod(HttpMethod::PATCH).setQueryString("param1=2¶m2=test2").send(); + auto future3 = httpRequest3.setMethod(HttpMethod::PATCH).setQueryString("param1=3¶m2=test3").send(); auto response1 = future1.get(); auto response2 = future2.get(); @@ -657,9 +657,9 @@ TEST(HttpPatchTest, MultipleHttpPatchRequestMustBeCompletedSuccessfullyInNonBloc TEST(HttpPatchTest, ResponseOfAnHttpPatchRequestCanBeReceivedInBinaryFormat) { - HttpClient httpClient("https://httpbun.com/bytes/100"); + HttpRequest httpRequest("https://httpbun.com/bytes/100"); - auto response = httpClient + auto response = httpRequest .setMethod(HttpMethod::PATCH) .returnAsBinary() .send() @@ -674,9 +674,9 @@ TEST(HttpPatchTest, ResponseOfAnHttpPatchRequestCanBeReceivedInBinaryFormat) { TEST(HttpPatchTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPatchRequestMadeToAnInvalidAddress) { - HttpClient httpClient("https://httpbun.com/not_found"); + HttpRequest httpRequest("https://httpbun.com/not_found"); - auto response = httpClient.setMethod(HttpMethod::PATCH).send().get(); + auto response = httpRequest.setMethod(HttpMethod::PATCH).send().get(); ASSERT_FALSE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 404) << "HTTP Status Code is not 404"; @@ -685,9 +685,9 @@ TEST(HttpPatchTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPatchRequest TEST(HttpPatchTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPatchRequestForAnotherError) { - HttpClient httpClient("https://httpbun.com/bearer"); + HttpRequest httpRequest("https://httpbun.com/bearer"); - auto response = httpClient.setMethod(HttpMethod::PATCH).send().get(); + auto response = httpRequest.setMethod(HttpMethod::PATCH).send().get(); ASSERT_FALSE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 401) << "HTTP Status Code is not 401"; @@ -696,9 +696,9 @@ TEST(HttpPatchTest, AnErrorMessageShouldBeReturnedInResponseToAnHttpPatchRequest TEST(HttpPatchTest, HttpHeadersCanBeSentWithTheHttpPatchRequest) { - HttpClient httpClient("https://httpbun.com/patch"); + HttpRequest httpRequest("https://httpbun.com/patch"); - auto response = httpClient + auto response = httpRequest .setMethod(HttpMethod::PATCH) .setQueryString("param1=7¶m2=test") .addHeader("Custom-Header1", "value1") @@ -724,9 +724,9 @@ TEST(HttpPatchTest, HttpHeadersCanBeSentWithTheHttpPatchRequest) { TEST(InvalidSSLTest, HttpGetRequestMustReturnErrorForAnInvalidSsl) { - HttpClient httpClient("https://self-signed-cert.httpbun.com"); + HttpRequest httpRequest("https://self-signed-cert.httpbun.com"); - auto response = httpClient.send().get(); + auto response = httpRequest.send().get(); ASSERT_FALSE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 0) << "HTTP Status Code is not 0"; @@ -735,9 +735,9 @@ TEST(InvalidSSLTest, HttpGetRequestMustReturnErrorForAnInvalidSsl) { TEST(InvalidSSLTest, HttpGetRequestMustBeCompletedSuccessfullyForAnInvalidSslIfIgnoreSslErrorsFieldSetTrue) { - HttpClient httpClient("https://self-signed-cert.httpbun.com"); + HttpRequest httpRequest("https://self-signed-cert.httpbun.com"); - auto response = httpClient.ignoreSslErrors().send().get(); + auto response = httpRequest.ignoreSslErrors().send().get(); ASSERT_TRUE(response.succeed) << "HTTP Request failed"; ASSERT_EQ(response.statusCode, 200) << "HTTP Status Code is not 200"; From 46f5a41c9cdda4e851020947e562f6b8f9703747 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Levent=20KARAG=C3=96L?= Date: Sun, 21 Apr 2024 14:24:51 +0300 Subject: [PATCH 3/7] Method overloading structure converted to Builder Pattern --- README.md | 64 +++++++++++++++++++++++++++---------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 0dd77d9..7095760 100644 --- a/README.md +++ b/README.md @@ -70,10 +70,10 @@ using namespace lklibs; int main() { - HttpClient httpClient; + HttpRequest httpRequest; // The simplest but slowest method if multiple calls will be made - auto response = httpClient.getRequest("https://api.myproject.com?param1=7¶m2=test").get(); + auto response = httpRequest.getRequest("https://api.myproject.com?param1=7¶m2=test").get(); std::cout << "Succeed: " << response.succeed << std::endl; std::cout << "Http Status Code: " << response.statusCode << std::endl; @@ -98,13 +98,13 @@ using namespace lklibs; int main() { - HttpClient httpClient; + HttpRequest httpRequest; - auto response1 = httpClient.getRequest("https://api.myproject.com/foo").get(); - auto response2 = httpClient.getRequest("https://api.myproject.com/bar").get(); - auto response3 = httpClient.getRequest("https://api.myproject.com/baz").get(); - auto response4 = httpClient.getRequest("https://api.myproject.com/qux").get(); - auto response5 = httpClient.getRequest("https://api.myproject.com/quux").get(); + auto response1 = httpRequest.getRequest("https://api.myproject.com/foo").get(); + auto response2 = httpRequest.getRequest("https://api.myproject.com/bar").get(); + auto response3 = httpRequest.getRequest("https://api.myproject.com/baz").get(); + auto response4 = httpRequest.getRequest("https://api.myproject.com/qux").get(); + auto response5 = httpRequest.getRequest("https://api.myproject.com/quux").get(); // Takes 2.5 seconds in total @@ -124,13 +124,13 @@ using namespace lklibs; int main() { - HttpClient httpClient; + HttpRequest httpRequest; - auto future1 = httpClient.getRequest("https://api.myproject.com/foo"); - auto future2 = httpClient.getRequest("https://api.myproject.com/bar"); - auto future3 = httpClient.getRequest("https://api.myproject.com/baz"); - auto future4 = httpClient.getRequest("https://api.myproject.com/qux"); - auto future5 = httpClient.getRequest("https://api.myproject.com/quux"); + auto future1 = httpRequest.getRequest("https://api.myproject.com/foo"); + auto future2 = httpRequest.getRequest("https://api.myproject.com/bar"); + auto future3 = httpRequest.getRequest("https://api.myproject.com/baz"); + auto future4 = httpRequest.getRequest("https://api.myproject.com/qux"); + auto future5 = httpRequest.getRequest("https://api.myproject.com/quux"); auto response1 = future1.get(); auto response2 = future2.get(); @@ -166,9 +166,9 @@ using namespace lklibs; int main() { - HttpClient httpClient; + HttpRequest httpRequest; - auto response = httpClient.getRequest("https://www.myinvalidurl.com").get(); + auto response = httpRequest.getRequest("https://www.myinvalidurl.com").get(); // Instead of throwing an exception, the succeed field of the response object is set to false std::cout << "Succeed: " << response.succeed << std::endl; @@ -200,10 +200,10 @@ using namespace lklibs; int main() { - HttpClient httpClient; + HttpRequest httpRequest; // If you need to retrieve binary data such as an image, just pass the "returnAsBinary" parameter as true - auto response = httpClient.getRequest("https://api.myproject.com/image/7", true).get(); + auto response = httpRequest.getRequest("https://api.myproject.com/image/7", true).get(); std::cout << "Succeed: " << response.succeed << std::endl; std::cout << "Http Status Code: " << response.statusCode << std::endl; @@ -229,7 +229,7 @@ using namespace lklibs; int main() { - HttpClient httpClient; + HttpRequest httpRequest; // You can send custom headers in a string/string map auto headers = std::map(); @@ -237,7 +237,7 @@ int main() { headers["Custom-Header1"] = "value1"; headers["Custom-Header2"] = "value2"; - auto response = httpClient.getRequest("https://api.myproject.com?param1=7¶m2=test", headers).get(); + auto response = httpRequest.getRequest("https://api.myproject.com?param1=7¶m2=test", headers).get(); std::cout << "Succeed: " << response.succeed << std::endl; @@ -259,12 +259,12 @@ using namespace lklibs; int main() { - HttpClient httpClient; + HttpRequest httpRequest; // You can send a POST request with form data in the payload std::string payload = "param1=7¶m2=test"; - auto response = httpClient.postRequest("https://api.myproject.com", payload).get(); + auto response = httpRequest.postRequest("https://api.myproject.com", payload).get(); std::cout << "Succeed: " << response.succeed << std::endl; std::cout << "Http Status Code: " << response.statusCode << std::endl; @@ -288,7 +288,7 @@ using namespace lklibs; int main() { - HttpClient httpClient; + HttpRequest httpRequest; std::string payload = R"({"param1": 7, "param2": "test"})"; @@ -297,7 +297,7 @@ int main() { headers["Content-Type"] = "application/json"; - auto response = httpClient.postRequest("https://api.myproject.com", payload, headers).get(); + auto response = httpRequest.postRequest("https://api.myproject.com", payload, headers).get(); std::cout << "Succeed: " << response.succeed << std::endl; std::cout << "Http Status Code: " << response.statusCode << std::endl; @@ -320,13 +320,13 @@ using namespace lklibs; int main() { - HttpClient httpClient; + HttpRequest httpRequest; std::string payload = "param1=7¶m2=test"; - auto future1 = httpClient.putRequest("https://api.myproject.com", payload); - auto future2 = httpClient.deleteRequest("https://api.myproject.com", payload); - auto future3 = httpClient.patchRequest("https://api.myproject.com?param1=7¶m2=test"); + auto future1 = httpRequest.putRequest("https://api.myproject.com", payload); + auto future2 = httpRequest.deleteRequest("https://api.myproject.com", payload); + auto future3 = httpRequest.patchRequest("https://api.myproject.com?param1=7¶m2=test"); auto response1 = future1.get(); auto response2 = future2.get(); @@ -341,7 +341,7 @@ int main() { If you need to ignore SSL certificate errors for any valid reason, you can continue working by passing **"true"** value to the **"ignoreSslErrors"** variable of the -HttpClient class. +HttpRequest class. ```cpp #include @@ -351,12 +351,12 @@ using namespace lklibs; int main() { - HttpClient httpClient; + HttpRequest httpRequest; // If you need to ignore SSL errors, you can set the "ignoreSslErrors" field to true - httpClient.ignoreSslErrors = true; + httpRequest.ignoreSslErrors = true; - auto response = httpClient.getRequest("https://api.myinvalidssl.com").get(); + auto response = httpRequest.getRequest("https://api.myinvalidssl.com").get(); return 0; } From 9bf9dc16323df6db45a1d0a894abd313419c9b46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Levent=20KARAG=C3=96L?= Date: Sun, 21 Apr 2024 14:39:22 +0300 Subject: [PATCH 4/7] Method overloading structure converted to Builder Pattern --- README.md | 193 ++++++++++++++++++++++------------------------ examples/main.cpp | 2 +- 2 files changed, 93 insertions(+), 102 deletions(-) diff --git a/README.md b/README.md index 7095760..d444b71 100644 --- a/README.md +++ b/README.md @@ -70,10 +70,13 @@ using namespace lklibs; int main() { - HttpRequest httpRequest; + HttpRequest httpRequest("https://api.myproject.com"); // The simplest but slowest method if multiple calls will be made - auto response = httpRequest.getRequest("https://api.myproject.com?param1=7¶m2=test").get(); + auto response = httpRequest + .setQueryString("param1=7¶m2=test") + .send() + .get(); std::cout << "Succeed: " << response.succeed << std::endl; std::cout << "Http Status Code: " << response.statusCode << std::endl; @@ -98,13 +101,17 @@ using namespace lklibs; int main() { - HttpRequest httpRequest; - - auto response1 = httpRequest.getRequest("https://api.myproject.com/foo").get(); - auto response2 = httpRequest.getRequest("https://api.myproject.com/bar").get(); - auto response3 = httpRequest.getRequest("https://api.myproject.com/baz").get(); - auto response4 = httpRequest.getRequest("https://api.myproject.com/qux").get(); - auto response5 = httpRequest.getRequest("https://api.myproject.com/quux").get(); + HttpRequest httpRequest1("https://api.myproject.com/foo"); + HttpRequest httpRequest2("https://api.myproject.com/bar"); + HttpRequest httpRequest3("https://api.myproject.com/baz"); + HttpRequest httpRequest4("https://api.myproject.com/qux"); + HttpRequest httpRequest5("https://api.myproject.com/quux"); + + auto response1 = httpRequest1.send().get(); + auto response2 = httpRequest2.send().get(); + auto response3 = httpRequest3.send().get(); + auto response4 = httpRequest4.send().get(); + auto response5 = httpRequest5.send().get(); // Takes 2.5 seconds in total @@ -124,13 +131,17 @@ using namespace lklibs; int main() { - HttpRequest httpRequest; - - auto future1 = httpRequest.getRequest("https://api.myproject.com/foo"); - auto future2 = httpRequest.getRequest("https://api.myproject.com/bar"); - auto future3 = httpRequest.getRequest("https://api.myproject.com/baz"); - auto future4 = httpRequest.getRequest("https://api.myproject.com/qux"); - auto future5 = httpRequest.getRequest("https://api.myproject.com/quux"); + HttpRequest httpRequest1("https://api.myproject.com/foo"); + HttpRequest httpRequest2("https://api.myproject.com/bar"); + HttpRequest httpRequest3("https://api.myproject.com/baz"); + HttpRequest httpRequest4("https://api.myproject.com/qux"); + HttpRequest httpRequest5("https://api.myproject.com/quux"); + + auto future1 = httpRequest.send(); + auto future2 = httpRequest.send(); + auto future3 = httpRequest.send(); + auto future4 = httpRequest.send(); + auto future5 = httpRequest.send(); auto response1 = future1.get(); auto response2 = future2.get(); @@ -166,9 +177,9 @@ using namespace lklibs; int main() { - HttpRequest httpRequest; + HttpRequest httpRequest("https://www.myinvalidurl.com"); - auto response = httpRequest.getRequest("https://www.myinvalidurl.com").get(); + auto response = httpRequest.send().get(); // Instead of throwing an exception, the succeed field of the response object is set to false std::cout << "Succeed: " << response.succeed << std::endl; @@ -200,10 +211,13 @@ using namespace lklibs; int main() { - HttpRequest httpRequest; + HttpRequest httpRequest("https://api.myproject.com/image/7"); - // If you need to retrieve binary data such as an image, just pass the "returnAsBinary" parameter as true - auto response = httpRequest.getRequest("https://api.myproject.com/image/7", true).get(); + // If you need to retrieve binary data such as an image, just call the "returnAsBinary" method before send + auto response = httpRequest + .returnAsBinary() + .send() + .get(); std::cout << "Succeed: " << response.succeed << std::endl; std::cout << "Http Status Code: " << response.statusCode << std::endl; @@ -229,16 +243,15 @@ using namespace lklibs; int main() { - HttpRequest httpRequest; - - // You can send custom headers in a string/string map - auto headers = std::map(); - - headers["Custom-Header1"] = "value1"; - headers["Custom-Header2"] = "value2"; - - auto response = httpRequest.getRequest("https://api.myproject.com?param1=7¶m2=test", headers).get(); - + HttpRequest httpRequest("https://api.myproject.com?param1=7¶m2=test"); + + // You can send custom headers as key-value pairs + auto response = httpRequest + .addHeader("Custom-Header1", "value1") + .addHeader("Custom-Header2", "value2") + .send() + .get(); + std::cout << "Succeed: " << response.succeed << std::endl; return 0; @@ -259,12 +272,14 @@ using namespace lklibs; int main() { - HttpRequest httpRequest; + HttpRequest httpRequest("https://api.myproject.com"); // You can send a POST request with form data in the payload - std::string payload = "param1=7¶m2=test"; - - auto response = httpRequest.postRequest("https://api.myproject.com", payload).get(); + auto response = httpRequest + .setMethod(HttpMethod::POST) + .setPayload("param1=7¶m2=test") + .send() + .get(); std::cout << "Succeed: " << response.succeed << std::endl; std::cout << "Http Status Code: " << response.statusCode << std::endl; @@ -288,16 +303,15 @@ using namespace lklibs; int main() { - HttpRequest httpRequest; - - std::string payload = R"({"param1": 7, "param2": "test"})"; - + HttpRequest httpRequest("https://api.myproject.com"); + // You need to send the "Content-Type" as "application/json" in the HTTP Header, if you need to send json data in the payload - auto headers = std::map(); - - headers["Content-Type"] = "application/json"; - - auto response = httpRequest.postRequest("https://api.myproject.com", payload, headers).get(); + auto response = httpRequest + .setMethod(HttpMethod::POST) + .setPayload(R"({"param1": 7, "param2": "test"})") + .addHeader("Content-Type", "application/json") + .send() + .get(); std::cout << "Succeed: " << response.succeed << std::endl; std::cout << "Http Status Code: " << response.statusCode << std::endl; @@ -320,13 +334,29 @@ using namespace lklibs; int main() { - HttpRequest httpRequest; + HttpRequest httpRequest1("https://api.myproject.com"); - std::string payload = "param1=7¶m2=test"; + auto future1 = httpRequest + .setMethod(HttpMethod::PUT) + .setPayload("param1=7¶m2=test") + .send() + .get(); + + HttpRequest httpRequest2("https://api.myproject.com"); - auto future1 = httpRequest.putRequest("https://api.myproject.com", payload); - auto future2 = httpRequest.deleteRequest("https://api.myproject.com", payload); - auto future3 = httpRequest.patchRequest("https://api.myproject.com?param1=7¶m2=test"); + auto future2 = httpRequest + .setMethod(HttpMethod::DELETE_) + .setPayload("param1=7¶m2=test") + .send() + .get(); + + HttpRequest httpRequest3("https://api.myproject.com"); + + auto future3 = httpRequest + .setMethod(HttpMethod::PATCH) + .setQueryString("param1=7¶m2=test") + .send() + .get(); auto response1 = future1.get(); auto response2 = future2.get(); @@ -351,12 +381,10 @@ using namespace lklibs; int main() { - HttpRequest httpRequest; - - // If you need to ignore SSL errors, you can set the "ignoreSslErrors" field to true - httpRequest.ignoreSslErrors = true; + HttpRequest httpRequest("https://api.myinvalidssl.com"); - auto response = httpRequest.getRequest("https://api.myinvalidssl.com").get(); + // If you need to ignore SSL errors, you can call "ignoreSslErrors" method before sending the request + auto response = httpRequest.ignoreSslErrors().send().get(); return 0; } @@ -381,58 +409,21 @@ section to the documentation. ## Full function list -You can find the complete list of functions in the library below. In fact, they are just -overloaded versions of 5 functions in total. +You can find the complete list of functions in the library below. Since all methods except +send return the class itself, they can be added one after the other like a chain. > [!TIP] > All methods and parameters descriptions are also available within the code as comment for IDEs. ```cpp -- getRequest - - std::future getRequest(const std::string &url) - - std::future getRequest(const std::string &url, bool returnAsBinary) - - std::future getRequest(const std::string &url, const std::map &headers) - - std::future getRequest(const std::string &url, bool returnAsBinary, const std::map &headers) - - -- postRequest - - std::future postRequest(const std::string &url) - - std::future postRequest(const std::string &url, const std::string &payload) - - std::future postRequest(const std::string &url, bool returnAsBinary) - - std::future postRequest(const std::string &url, const std::map &headers) - - std::future postRequest(const std::string &url, const std::string &payload, bool returnAsBinary) - - std::future postRequest(const std::string &url, const std::string &payload, const std::map &headers) - - std::future postRequest(const std::string &url, bool returnAsBinary, const std::map &headers) - - std::future postRequest(const std::string &url, const std::string &payload, bool returnAsBinary, const std::map &headers) - - -- putRequest - - std::future putRequest(const std::string &url) - - std::future putRequest(const std::string &url, const std::string &payload) - - std::future putRequest(const std::string &url, bool returnAsBinary) - - std::future putRequest(const std::string &url, const std::map &headers) - - std::future putRequest(const std::string &url, const std::string &payload, bool returnAsBinary) - - std::future putRequest(const std::string &url, const std::string &payload, const std::map &headers) - - std::future putRequest(const std::string &url, bool returnAsBinary, const std::map &headers) - - std::future putRequest(const std::string &url, const std::string &payload, bool returnAsBinary, const std::map &headers) - - -- deleteRequest - - std::future deleteRequest(const std::string &url) - - std::future deleteRequest(const std::string &url, const std::string &payload) - - std::future deleteRequest(const std::string &url, bool returnAsBinary) - - std::future deleteRequest(const std::string &url, const std::map &headers) - - std::future deleteRequest(const std::string &url, const std::string &payload, bool returnAsBinary) - - std::future deleteRequest(const std::string &url, const std::string &payload, const std::map &headers) - - std::future deleteRequest(const std::string &url, bool returnAsBinary, const std::map &headers) - - std::future deleteRequest(const std::string &url, const std::string &payload, bool returnAsBinary, const std::map &headers) - - -- patchRequest - - std::future patchRequest(const std::string &url) - - std::future patchRequest(const std::string &url, bool returnAsBinary) - - std::future patchRequest(const std::string &url, const std::map &headers) - - std::future patchRequest(const std::string &url, bool returnAsBinary, const std::map &headers) +- HttpRequest &setMethod(const HttpMethod &method) +- HttpRequest &setQueryString(const std::string &queryString) +- HttpRequest &setPayload(const std::string &payload) +- HttpRequest &returnAsBinary() +- HttpRequest &ignoreSslErrors() +- HttpRequest &addHeader(const std::string &key, const std::string &value) +- std::future send() noexcept + ``` diff --git a/examples/main.cpp b/examples/main.cpp index 51544bb..9792bf1 100644 --- a/examples/main.cpp +++ b/examples/main.cpp @@ -51,7 +51,7 @@ void receiveBinaryData() { HttpRequest httpRequest("https://httpbun.com/bytes/100"); - // If you need to retrieve binary data such as an image, just call the "returnAsBinary" method + // If you need to retrieve binary data such as an image, just call the "returnAsBinary" method before send auto response = httpRequest .returnAsBinary() .send() From 320d57e8839837efd87cd33d0a37cf5001b0375f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Levent=20KARAG=C3=96L?= Date: Sun, 21 Apr 2024 14:50:32 +0300 Subject: [PATCH 5/7] Method overloading structure converted to Builder Pattern --- src/libcpp-http-client.hpp | 39 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/src/libcpp-http-client.hpp b/src/libcpp-http-client.hpp index 18d6fd0..e79241c 100644 --- a/src/libcpp-http-client.hpp +++ b/src/libcpp-http-client.hpp @@ -115,24 +115,9 @@ namespace lklibs { * * @param method: HTTP method to be used for the request */ - HttpRequest &setMethod(const HttpMethod &method) { - - this->method = [method] { - switch (method) { - case HttpMethod::GET: - return "GET"; - case HttpMethod::POST: - return "POST"; - case HttpMethod::PUT: - return "PUT"; - case HttpMethod::DELETE_: - return "DELETE"; - case HttpMethod::PATCH: - return "PATCH"; - default: - return "GET"; - } - }(); + HttpRequest &setMethod(const HttpMethod &method) noexcept { + + this->method = HttpMethodStrings[static_cast(method)]; return *this; } @@ -142,7 +127,7 @@ namespace lklibs { * * @param queryString: Query string to be sent with the request */ - HttpRequest &setQueryString(const std::string &queryString) { + HttpRequest &setQueryString(const std::string &queryString) noexcept { if (this->url.find('?') != std::string::npos) { @@ -163,7 +148,7 @@ namespace lklibs { * * @param payload: Payload to be sent with the request */ - HttpRequest &setPayload(const std::string &payload) { + HttpRequest &setPayload(const std::string &payload) noexcept { this->payload = payload; @@ -173,7 +158,7 @@ namespace lklibs { /** * @brief Set the return format for the request as binary */ - HttpRequest &returnAsBinary() { + HttpRequest &returnAsBinary() noexcept { this->returnFormat = ReturnFormat::BINARY; @@ -183,7 +168,7 @@ namespace lklibs { /** * @brief Ignore SSL errors when making HTTP requests */ - HttpRequest &ignoreSslErrors() { + HttpRequest &ignoreSslErrors() noexcept { this->sslErrorsWillBeIgnored = true; @@ -196,7 +181,7 @@ namespace lklibs { * @param key: Header key * @param value: Header value */ - HttpRequest &addHeader(const std::string &key, const std::string &value) { + HttpRequest &addHeader(const std::string &key, const std::string &value) noexcept { this->headers[key] = value; @@ -223,6 +208,14 @@ namespace lklibs { BINARY }; + const char* HttpMethodStrings[5] = { + "GET", + "POST", + "PUT", + "DELETE", + "PATCH" + }; + std::string url; std::string method = "GET"; std::string payload; From b5f945af6416a7ddff1e0cb1ef04d72391e657e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Levent=20KARAG=C3=96L?= Date: Sun, 21 Apr 2024 15:31:34 +0300 Subject: [PATCH 6/7] Method overloading structure converted to Builder Pattern --- README.md | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index d444b71..390557a 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ target_link_libraries(myProject PRIVATE libcpp-http-client CURL::libcurl) Below you can see the simplest use case sending QueryString parameters to an API via HTTP GET. > [!IMPORTANT] -> Please do not use it this way, if more than one call will be made . You do not use the non-blocking +> Please do not use it this way, if more than one call will be made. You do not use the non-blocking > feature in this way. Just keep reading... ```cpp @@ -155,7 +155,7 @@ int main() { } ``` -All functions in the library return a future and allow the next line to run without blocking the flow. +**"send"** function in the library return a future and allow the next line to run without blocking the flow. ## What does exception free mean? @@ -200,8 +200,7 @@ int main() { In the examples so far, we have used the **"textData"** property of the returning response object. However, we need binary data for requests made to binary files such as images. In such cases, we can ensure that the returned data is returned in **"binaryData"** of type -***"std::vector<unsigned char>"*** instead of **"textData"** by passing the value **"true"** -to the **"returnAsBinary"** parameter. +***"std::vector<unsigned char>"*** instead of **"textData"** by calling **"returnAsBinary()"** method before send as follow. ```cpp #include @@ -232,8 +231,7 @@ int main() { ## Sending custom HTTP headers -If you need to send custom HTTP HEADERs during the request, you can send them in -std::map format. +If you need to send custom HTTP HEADERs during the request, you can add them to the request as key-value pairs with **"addHeader()"** method. ```cpp #include @@ -243,7 +241,7 @@ using namespace lklibs; int main() { - HttpRequest httpRequest("https://api.myproject.com?param1=7¶m2=test"); + HttpRequest httpRequest("https://api.myproject.com"); // You can send custom headers as key-value pairs auto response = httpRequest @@ -261,8 +259,7 @@ int main() { ## POST request with form data -Next is submitting form data via HTTP POST. All you have to do is use **"postRequest"** instead -of **"getRequest"**. You can pass the form data to the **"payload"** variable as seen in the sample code below. +Next is submitting form data via HTTP POST. All you have to do is use **"setMethod"** to change HTTP method type. You can pass the form data with **"setPaylod"** method as seen in the sample code below. ```cpp #include @@ -339,24 +336,21 @@ int main() { auto future1 = httpRequest .setMethod(HttpMethod::PUT) .setPayload("param1=7¶m2=test") - .send() - .get(); + .send(); HttpRequest httpRequest2("https://api.myproject.com"); auto future2 = httpRequest .setMethod(HttpMethod::DELETE_) .setPayload("param1=7¶m2=test") - .send() - .get(); + .send(); HttpRequest httpRequest3("https://api.myproject.com"); auto future3 = httpRequest .setMethod(HttpMethod::PATCH) .setQueryString("param1=7¶m2=test") - .send() - .get(); + .send(); auto response1 = future1.get(); auto response2 = future2.get(); @@ -369,9 +363,8 @@ int main() { ## How to ignore SSL certificate errors? -If you need to ignore SSL certificate errors for any valid reason, you can continue -working by passing **"true"** value to the **"ignoreSslErrors"** variable of the -HttpRequest class. +If you need to ignore SSL certificate errors for any valid reason, you can call "ignoreSslErrors" +method before sending the request. ```cpp #include @@ -384,7 +377,10 @@ int main() { HttpRequest httpRequest("https://api.myinvalidssl.com"); // If you need to ignore SSL errors, you can call "ignoreSslErrors" method before sending the request - auto response = httpRequest.ignoreSslErrors().send().get(); + auto response = httpRequest + .ignoreSslErrors() + .send() + .get(); return 0; } @@ -410,7 +406,7 @@ section to the documentation. ## Full function list You can find the complete list of functions in the library below. Since all methods except -send return the class itself, they can be added one after the other like a chain. +send return the class itself, so they can be added one after the other like a chain. > [!TIP] > All methods and parameters descriptions are also available within the code as comment for IDEs. From 559647c8e43efc06c67e6ec8bfeaa2f395722100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Levent=20KARAG=C3=96L?= Date: Sun, 21 Apr 2024 15:35:43 +0300 Subject: [PATCH 7/7] Method overloading structure converted to Builder Pattern --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 390557a..3906430 100644 --- a/README.md +++ b/README.md @@ -412,12 +412,12 @@ send return the class itself, so they can be added one after the other like a ch > All methods and parameters descriptions are also available within the code as comment for IDEs. ```cpp -- HttpRequest &setMethod(const HttpMethod &method) -- HttpRequest &setQueryString(const std::string &queryString) -- HttpRequest &setPayload(const std::string &payload) -- HttpRequest &returnAsBinary() -- HttpRequest &ignoreSslErrors() -- HttpRequest &addHeader(const std::string &key, const std::string &value) +- HttpRequest &setMethod(const HttpMethod &method) noexcept +- HttpRequest &setQueryString(const std::string &queryString) noexcept +- HttpRequest &setPayload(const std::string &payload) noexcept +- HttpRequest &returnAsBinary() noexcept +- HttpRequest &ignoreSslErrors() noexcept +- HttpRequest &addHeader(const std::string &key, const std::string &value) noexcept - std::future send() noexcept ```