Breaking changes on the client, push only for keeping the history.
This commit is contained in:
@@ -1,13 +1,27 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
|
|
||||||
#include "webcc/logger.h"
|
#include "webcc/logger.h"
|
||||||
#include "webcc/rest_ssl_client.h"
|
#include "webcc/rest_ssl_client.h"
|
||||||
|
|
||||||
const bool kSslVerify = false;
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
#define PRINT_CONTENT 0
|
// Change to 1 to print response JSON.
|
||||||
|
#define PRINT_RESPONSE 0
|
||||||
|
|
||||||
|
#if (defined(WIN32) || defined(_WIN64))
|
||||||
|
// You need to set environment variable SSL_CERT_FILE properly to enable
|
||||||
|
// SSL verification.
|
||||||
|
bool kSslVerify = false;
|
||||||
|
#else
|
||||||
|
bool kSslVerify = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const std::string kGithubHost = "api.github.com";
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
static Json::Value StringToJson(const std::string& str) {
|
static Json::Value StringToJson(const std::string& str) {
|
||||||
Json::Value json;
|
Json::Value json;
|
||||||
@@ -22,64 +36,76 @@ static Json::Value StringToJson(const std::string& str) {
|
|||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListPublicEvents() {
|
// Print the JSON string in pretty format.
|
||||||
webcc::RestSslClient client("api.github.com", "", kSslVerify);
|
static void PrettyPrintJsonString(const std::string& str) {
|
||||||
|
Json::Value json = StringToJson(str);
|
||||||
|
|
||||||
|
Json::StreamWriterBuilder builder;
|
||||||
|
builder["indentation"] = " ";
|
||||||
|
|
||||||
|
std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
|
||||||
|
writer->write(json, &std::cout);
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if PRINT_RESPONSE
|
||||||
|
#define PRINT_JSON_STRING(str) PrettyPrintJsonString(str)
|
||||||
|
#else
|
||||||
|
#define PRINT_JSON_STRING(str)
|
||||||
|
#endif // PRINT_RESPONSE
|
||||||
|
|
||||||
|
static void PrintError(const webcc::RestSslClient& client) {
|
||||||
|
std::cout << webcc::DescribeError(client.error());
|
||||||
|
if (client.timed_out()) {
|
||||||
|
std::cout << " (timed out)";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// List public events.
|
||||||
|
static void ListEvents(webcc::RestSslClient& client) {
|
||||||
if (client.Get("/events")) {
|
if (client.Get("/events")) {
|
||||||
#if PRINT_CONTENT
|
PRINT_JSON_STRING(client.response_content());
|
||||||
Json::Value json = StringToJson(client.response()->content());
|
|
||||||
|
|
||||||
// Pretty print the JSON.
|
|
||||||
|
|
||||||
Json::StreamWriterBuilder builder;
|
|
||||||
builder["indentation"] = " ";
|
|
||||||
|
|
||||||
std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
|
|
||||||
writer->write(json, &std::cout);
|
|
||||||
|
|
||||||
std::cout << std::endl;
|
|
||||||
#endif // PRINT_CONTENT
|
|
||||||
} else {
|
} else {
|
||||||
std::cout << webcc::DescribeError(client.error());
|
PrintError(client);
|
||||||
if (client.timed_out()) {
|
|
||||||
std::cout << " (timed out)";
|
|
||||||
}
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListUserFollowers() {
|
// List the followers of the given user.
|
||||||
webcc::RestSslClient client("api.github.com", "", kSslVerify);
|
static void ListUserFollowers(webcc::RestSslClient& client,
|
||||||
|
const std::string& user) {
|
||||||
if (client.Get("/users/sprinfall/followers")) {
|
if (client.Get("/users/" + user + "/followers")) {
|
||||||
#if PRINT_CONTENT
|
PRINT_JSON_STRING(client.response_content());
|
||||||
Json::Value json = StringToJson(client.response()->content());
|
|
||||||
|
|
||||||
// Pretty print the JSON.
|
|
||||||
|
|
||||||
Json::StreamWriterBuilder builder;
|
|
||||||
builder["indentation"] = " ";
|
|
||||||
|
|
||||||
std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
|
|
||||||
writer->write(json, &std::cout);
|
|
||||||
|
|
||||||
std::cout << std::endl;
|
|
||||||
#endif // PRINT_CONTENT
|
|
||||||
} else {
|
} else {
|
||||||
std::cout << webcc::DescribeError(client.error());
|
PrintError(client);
|
||||||
if (client.timed_out()) {
|
|
||||||
std::cout << " (timed out)";
|
|
||||||
}
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// List the followers of the current authorized user.
|
||||||
|
// Header syntax: Authorization: <type> <credentials>
|
||||||
|
static void ListAuthorizedUserFollowers(webcc::RestSslClient& client,
|
||||||
|
const std::string& auth) {
|
||||||
|
if (client.Get("/user/followers", { { "Authorization", auth } })) {
|
||||||
|
PRINT_JSON_STRING(client.response_content());
|
||||||
|
} else {
|
||||||
|
PrintError(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
WEBCC_LOG_INIT("", webcc::LOG_CONSOLE);
|
WEBCC_LOG_INIT("", webcc::LOG_CONSOLE);
|
||||||
|
|
||||||
//ListPublicEvents();
|
webcc::RestSslClient client(kGithubHost, "", kSslVerify, {}, 1500);
|
||||||
|
|
||||||
ListUserFollowers();
|
//ListAuthorizedUserFollowers(client, "Basic c3ByaW5mYWxsQGdtYWlsLmNvbTpYaWFvTHVhbjFA");
|
||||||
|
ListAuthorizedUserFollowers(client, "Token 1d42e2cce49929f2d24b1b6e96260003e5b3e1b0");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,25 +23,38 @@ class BookClientBase {
|
|||||||
public:
|
public:
|
||||||
BookClientBase(const std::string& host, const std::string& port,
|
BookClientBase(const std::string& host, const std::string& port,
|
||||||
int timeout_seconds)
|
int timeout_seconds)
|
||||||
: rest_client_(host, port) {
|
: host_(host), port_(port) {
|
||||||
rest_client_.SetTimeout(timeout_seconds);
|
http_client_.SetTimeout(timeout_seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~BookClientBase() = default;
|
virtual ~BookClientBase() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// Helper function to make a request.
|
||||||
|
webcc::HttpRequestPtr MakeRequest(const std::string& method,
|
||||||
|
const std::string& url,
|
||||||
|
std::string&& content = "") {
|
||||||
|
auto request = webcc::HttpRequest::New(method, url, host_, port_);
|
||||||
|
request->AcceptAppJson();
|
||||||
|
if (!content.empty()) {
|
||||||
|
request->SetContentInAppJsonUtf8(JsonToString(content), true);
|
||||||
|
}
|
||||||
|
request->Prepare();
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
// Log the socket communication error.
|
// Log the socket communication error.
|
||||||
void LogError() {
|
void LogError() {
|
||||||
if (rest_client_.timed_out()) {
|
if (http_client_.timed_out()) {
|
||||||
LOG_ERRO("%s (timed out)", webcc::DescribeError(rest_client_.error()));
|
LOG_ERRO("%s (timed out)", webcc::DescribeError(http_client_.error()));
|
||||||
} else {
|
} else {
|
||||||
LOG_ERRO(webcc::DescribeError(rest_client_.error()));
|
LOG_ERRO(webcc::DescribeError(http_client_.error()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check HTTP response status.
|
// Check HTTP response status.
|
||||||
bool CheckStatus(webcc::http::Status expected_status) {
|
bool CheckStatus(webcc::http::Status expected_status) {
|
||||||
int status = rest_client_.response_status();
|
int status = http_client_.response_status();
|
||||||
if (status != expected_status) {
|
if (status != expected_status) {
|
||||||
LOG_ERRO("HTTP status error (actual: %d, expected: %d).",
|
LOG_ERRO("HTTP status error (actual: %d, expected: %d).",
|
||||||
status, expected_status);
|
status, expected_status);
|
||||||
@@ -50,7 +63,9 @@ class BookClientBase {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
webcc::RestClient rest_client_;
|
std::string host_;
|
||||||
|
std::string port_;
|
||||||
|
webcc::HttpClient http_client_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -63,7 +78,9 @@ class BookListClient : public BookClientBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ListBooks(std::list<Book>* books) {
|
bool ListBooks(std::list<Book>* books) {
|
||||||
if (!rest_client_.Get("/books")) {
|
auto request = MakeRequest(webcc::kHttpGet, "/books");
|
||||||
|
|
||||||
|
if (!http_client_.Request(*request)) {
|
||||||
// Socket communication error.
|
// Socket communication error.
|
||||||
LogError();
|
LogError();
|
||||||
return false;
|
return false;
|
||||||
@@ -74,7 +91,7 @@ class BookListClient : public BookClientBase {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value rsp_json = StringToJson(rest_client_.response_content());
|
Json::Value rsp_json = StringToJson(http_client_.response_content());
|
||||||
|
|
||||||
if (!rsp_json.isArray()) {
|
if (!rsp_json.isArray()) {
|
||||||
return false; // Should be a JSON array of books.
|
return false; // Should be a JSON array of books.
|
||||||
@@ -92,7 +109,10 @@ class BookListClient : public BookClientBase {
|
|||||||
req_json["title"] = title;
|
req_json["title"] = title;
|
||||||
req_json["price"] = price;
|
req_json["price"] = price;
|
||||||
|
|
||||||
if (!rest_client_.Post("/books", JsonToString(req_json))) {
|
auto request = MakeRequest(webcc::kHttpPost, "/books",
|
||||||
|
JsonToString(req_json));
|
||||||
|
|
||||||
|
if (!http_client_.Request(*request)) {
|
||||||
LogError();
|
LogError();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -101,7 +121,7 @@ class BookListClient : public BookClientBase {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value rsp_json = StringToJson(rest_client_.response_content());
|
Json::Value rsp_json = StringToJson(http_client_.response_content());
|
||||||
*id = rsp_json["id"].asString();
|
*id = rsp_json["id"].asString();
|
||||||
|
|
||||||
return !id->empty();
|
return !id->empty();
|
||||||
@@ -118,7 +138,9 @@ class BookDetailClient : public BookClientBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool GetBook(const std::string& id, Book* book) {
|
bool GetBook(const std::string& id, Book* book) {
|
||||||
if (!rest_client_.Get("/books/" + id)) {
|
auto request = MakeRequest(webcc::kHttpGet, "/books/" + id);
|
||||||
|
|
||||||
|
if (!http_client_.Request(*request)) {
|
||||||
LogError();
|
LogError();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -127,7 +149,7 @@ class BookDetailClient : public BookClientBase {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return JsonStringToBook(rest_client_.response_content(), book);
|
return JsonStringToBook(http_client_.response_content(), book);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UpdateBook(const std::string& id, const std::string& title,
|
bool UpdateBook(const std::string& id, const std::string& title,
|
||||||
@@ -136,7 +158,10 @@ class BookDetailClient : public BookClientBase {
|
|||||||
json["title"] = title;
|
json["title"] = title;
|
||||||
json["price"] = price;
|
json["price"] = price;
|
||||||
|
|
||||||
if (!rest_client_.Put("/books/" + id, JsonToString(json))) {
|
auto request = MakeRequest(webcc::kHttpPut, "/books/" + id,
|
||||||
|
JsonToString(json));
|
||||||
|
|
||||||
|
if (!http_client_.Request(*request)) {
|
||||||
LogError();
|
LogError();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -149,7 +174,9 @@ class BookDetailClient : public BookClientBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool DeleteBook(const std::string& id) {
|
bool DeleteBook(const std::string& id) {
|
||||||
if (!rest_client_.Delete("/books/" + id)) {
|
auto request = MakeRequest(webcc::kHttpDelete, "/books/" + id);
|
||||||
|
|
||||||
|
if (!http_client_.Request(*request)) {
|
||||||
LogError();
|
LogError();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -238,26 +265,26 @@ int main(int argc, char* argv[]) {
|
|||||||
PrintBook(book);
|
PrintBook(book);
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintSeparator();
|
//PrintSeparator();
|
||||||
|
|
||||||
detail_client.UpdateBook(id, "1Q84", 32.1);
|
//detail_client.UpdateBook(id, "1Q84", 32.1);
|
||||||
|
|
||||||
PrintSeparator();
|
//PrintSeparator();
|
||||||
|
|
||||||
if (detail_client.GetBook(id, &book)) {
|
//if (detail_client.GetBook(id, &book)) {
|
||||||
PrintBook(book);
|
// PrintBook(book);
|
||||||
}
|
//}
|
||||||
|
|
||||||
PrintSeparator();
|
//PrintSeparator();
|
||||||
|
|
||||||
detail_client.DeleteBook(id);
|
//detail_client.DeleteBook(id);
|
||||||
|
|
||||||
PrintSeparator();
|
//PrintSeparator();
|
||||||
|
|
||||||
books.clear();
|
//books.clear();
|
||||||
if (list_client.ListBooks(&books)) {
|
//if (list_client.ListBooks(&books)) {
|
||||||
PrintBookList(books);
|
// PrintBookList(books);
|
||||||
}
|
//}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ class HttpAsyncClientBase
|
|||||||
explicit HttpAsyncClientBase(boost::asio::io_context& io_context,
|
explicit HttpAsyncClientBase(boost::asio::io_context& io_context,
|
||||||
std::size_t buffer_size = 0);
|
std::size_t buffer_size = 0);
|
||||||
|
|
||||||
|
virtual ~HttpAsyncClientBase() = default;
|
||||||
|
|
||||||
WEBCC_DELETE_COPY_ASSIGN(HttpAsyncClientBase);
|
WEBCC_DELETE_COPY_ASSIGN(HttpAsyncClientBase);
|
||||||
|
|
||||||
// Set the timeout seconds for reading response.
|
// Set the timeout seconds for reading response.
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class HttpClientBase {
|
|||||||
// 0 means default value (e.g., 1024) will be used.
|
// 0 means default value (e.g., 1024) will be used.
|
||||||
explicit HttpClientBase(std::size_t buffer_size = 0);
|
explicit HttpClientBase(std::size_t buffer_size = 0);
|
||||||
|
|
||||||
~HttpClientBase() = default;
|
virtual ~HttpClientBase() = default;
|
||||||
|
|
||||||
WEBCC_DELETE_COPY_ASSIGN(HttpClientBase);
|
WEBCC_DELETE_COPY_ASSIGN(HttpClientBase);
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,12 @@ void HttpMessage::SetContent(std::string&& content, bool set_length) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HttpMessage::SetContentInAppJsonUtf8(std::string&& content,
|
||||||
|
bool set_length) {
|
||||||
|
SetContent(std::move(content), set_length);
|
||||||
|
SetContentType(http::media_types::kApplicationJson, http::charsets::kUtf8);
|
||||||
|
}
|
||||||
|
|
||||||
// ATTENTION: The buffers don't hold the memory!
|
// ATTENTION: The buffers don't hold the memory!
|
||||||
std::vector<boost::asio::const_buffer> HttpMessage::ToBuffers() const {
|
std::vector<boost::asio::const_buffer> HttpMessage::ToBuffers() const {
|
||||||
assert(!start_line_.empty());
|
assert(!start_line_.empty());
|
||||||
|
|||||||
@@ -34,16 +34,21 @@ class HttpMessage {
|
|||||||
|
|
||||||
const std::string& content() const { return content_; }
|
const std::string& content() const { return content_; }
|
||||||
|
|
||||||
|
// TODO: Rename to AddHeader.
|
||||||
void SetHeader(const std::string& name, const std::string& value);
|
void SetHeader(const std::string& name, const std::string& value);
|
||||||
|
|
||||||
|
// TODO: Remove
|
||||||
void SetHeader(std::string&& name, std::string&& value);
|
void SetHeader(std::string&& name, std::string&& value);
|
||||||
|
|
||||||
// E.g., "application/json; charset=utf-8"
|
// E.g., "application/json; charset=utf-8"
|
||||||
void SetContentType(const std::string& media_type,
|
void SetContentType(const std::string& media_type,
|
||||||
const std::string& charset);
|
const std::string& charset);
|
||||||
|
|
||||||
|
// TODO: Remove parameter |set_length|.
|
||||||
void SetContent(std::string&& content, bool set_length);
|
void SetContent(std::string&& content, bool set_length);
|
||||||
|
|
||||||
|
void SetContentInAppJsonUtf8(std::string&& content, bool set_length);
|
||||||
|
|
||||||
// Make the message (e.g., update start line).
|
// Make the message (e.g., update start line).
|
||||||
// Must be called before ToBuffers()!
|
// Must be called before ToBuffers()!
|
||||||
virtual void Prepare() = 0;
|
virtual void Prepare() = 0;
|
||||||
|
|||||||
@@ -39,6 +39,16 @@ class HttpRequest : public HttpMessage {
|
|||||||
return port_.empty() ? default_port : port_;
|
return port_.empty() ? default_port : port_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shortcut to set `Accept` header.
|
||||||
|
void Accept(const std::string& media_type) {
|
||||||
|
SetHeader(http::headers::kAccept, media_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shortcut to set `Accept` header.
|
||||||
|
void AcceptAppJson() {
|
||||||
|
SetHeader(http::headers::kAccept, http::media_types::kApplicationJson);
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare payload.
|
// Prepare payload.
|
||||||
// Compose start line, set Host header, etc.
|
// Compose start line, set Host header, etc.
|
||||||
void Prepare() override;
|
void Prepare() override;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace ssl = boost::asio::ssl;
|
|||||||
|
|
||||||
namespace webcc {
|
namespace webcc {
|
||||||
|
|
||||||
HttpSslClient::HttpSslClient(std::size_t buffer_size, bool ssl_verify)
|
HttpSslClient::HttpSslClient(bool ssl_verify, std::size_t buffer_size)
|
||||||
: HttpClientBase(buffer_size),
|
: HttpClientBase(buffer_size),
|
||||||
ssl_context_(ssl::context::sslv23),
|
ssl_context_(ssl::context::sslv23),
|
||||||
ssl_socket_(io_context_, ssl_context_),
|
ssl_socket_(io_context_, ssl_context_),
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class HttpSslClient : public HttpClientBase {
|
|||||||
// SSL verification (|ssl_verify|) needs CA certificates to be found
|
// SSL verification (|ssl_verify|) needs CA certificates to be found
|
||||||
// in the default verify paths of OpenSSL. On Windows, it means you need to
|
// in the default verify paths of OpenSSL. On Windows, it means you need to
|
||||||
// set environment variable SSL_CERT_FILE properly.
|
// set environment variable SSL_CERT_FILE properly.
|
||||||
explicit HttpSslClient(std::size_t buffer_size = 0, bool ssl_verify = true);
|
explicit HttpSslClient(bool ssl_verify = true, std::size_t buffer_size = 0);
|
||||||
|
|
||||||
~HttpSslClient() = default;
|
~HttpSslClient() = default;
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ void RestRequestHandler::HandleSession(HttpSessionPtr session) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Let the service to provide the media-type and charset.
|
||||||
RestResponse rest_response;
|
RestResponse rest_response;
|
||||||
service->Handle(rest_request, &rest_response);
|
service->Handle(rest_request, &rest_response);
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +1,50 @@
|
|||||||
#include "webcc/rest_ssl_client.h"
|
#include "webcc/rest_ssl_client.h"
|
||||||
|
|
||||||
|
#include "boost/algorithm/string.hpp"
|
||||||
|
|
||||||
#include "webcc/utility.h"
|
#include "webcc/utility.h"
|
||||||
|
|
||||||
namespace webcc {
|
namespace webcc {
|
||||||
|
|
||||||
|
RestClientBase::RestClientBase(HttpClientBase* http_client_base,
|
||||||
|
const SSMap& headers)
|
||||||
|
: http_client_base_(http_client_base),
|
||||||
|
content_media_type_(http::media_types::kApplicationJson),
|
||||||
|
content_charset_(http::charsets::kUtf8),
|
||||||
|
headers_(headers) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
RestSslClient::RestSslClient(const std::string& host, const std::string& port,
|
RestSslClient::RestSslClient(const std::string& host, const std::string& port,
|
||||||
std::size_t buffer_size, bool ssl_verify)
|
bool ssl_verify, const SSMap& headers,
|
||||||
: host_(host), port_(port),
|
std::size_t buffer_size)
|
||||||
http_client_(buffer_size, ssl_verify) {
|
: RestClientBase(&http_ssl_client_, headers),
|
||||||
|
host_(host), port_(port),
|
||||||
|
http_ssl_client_(ssl_verify, buffer_size) {
|
||||||
AdjustHostPort(host_, port_);
|
AdjustHostPort(host_, port_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RestSslClient::Request(const std::string& method, const std::string& url,
|
bool RestSslClient::Request(const std::string& method, const std::string& url,
|
||||||
std::string&& content, std::size_t buffer_size) {
|
std::string&& content, const SSMap& headers,
|
||||||
|
std::size_t buffer_size) {
|
||||||
HttpRequest http_request(method, url, host_, port_);
|
HttpRequest http_request(method, url, host_, port_);
|
||||||
|
|
||||||
if (!content.empty()) {
|
if (!content.empty()) {
|
||||||
http_request.SetContent(std::move(content), true);
|
http_request.SetContent(std::move(content), true);
|
||||||
http_request.SetContentType(http::media_types::kApplicationJson,
|
http_request.SetContentType(content_media_type_, content_charset_);
|
||||||
http::charsets::kUtf8);
|
}
|
||||||
|
|
||||||
|
for (auto& h : headers_) {
|
||||||
|
http_request.SetHeader(h.first, h.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& h : headers) {
|
||||||
|
http_request.SetHeader(h.first, h.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
http_request.Prepare();
|
http_request.Prepare();
|
||||||
|
|
||||||
if (!http_client_.Request(http_request, buffer_size)) {
|
if (!http_ssl_client_.Request(http_request, buffer_size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+79
-44
@@ -2,6 +2,7 @@
|
|||||||
#define WEBCC_REST_SSL_CLIENT_H_
|
#define WEBCC_REST_SSL_CLIENT_H_
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility> // for move()
|
#include <utility> // for move()
|
||||||
|
|
||||||
@@ -12,54 +13,30 @@
|
|||||||
|
|
||||||
namespace webcc {
|
namespace webcc {
|
||||||
|
|
||||||
class RestSslClient {
|
typedef std::map<std::string, std::string> SSMap;
|
||||||
|
|
||||||
|
class RestClientBase {
|
||||||
public:
|
public:
|
||||||
// If |port| is empty, |host| will be checked to see if it contains port or
|
RestClientBase(HttpClientBase* http_client_base,
|
||||||
// not (separated by ':').
|
const SSMap& headers = {});
|
||||||
explicit RestSslClient(const std::string& host,
|
|
||||||
const std::string& port = "",
|
|
||||||
std::size_t buffer_size = 0,
|
|
||||||
bool ssl_verify = true);
|
|
||||||
|
|
||||||
~RestSslClient() = default;
|
virtual ~RestClientBase() = default;
|
||||||
|
|
||||||
WEBCC_DELETE_COPY_ASSIGN(RestSslClient);
|
WEBCC_DELETE_COPY_ASSIGN(RestClientBase);
|
||||||
|
|
||||||
void SetTimeout(int seconds) {
|
void SetTimeout(int seconds) {
|
||||||
http_client_.SetTimeout(seconds);
|
http_client_base_->SetTimeout(seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE:
|
// Overwrite the default content type (json & utf-8).
|
||||||
// The return value of the following methods (Get, Post, etc.) only indicates
|
void SetContentType(const std::string& media_type,
|
||||||
// if the socket communication is successful or not. Check error() and
|
const std::string& charset) {
|
||||||
// timed_out() for more information if it's failed. Check response_status()
|
content_media_type_ = media_type;
|
||||||
// instead for the HTTP status code.
|
content_charset_ = charset;
|
||||||
|
|
||||||
inline bool Get(const std::string& url, std::size_t buffer_size = 0) {
|
|
||||||
return Request(kHttpGet, url, "", buffer_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool Post(const std::string& url, std::string&& content,
|
|
||||||
std::size_t buffer_size = 0) {
|
|
||||||
return Request(kHttpPost, url, std::move(content), buffer_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool Put(const std::string& url, std::string&& content,
|
|
||||||
std::size_t buffer_size = 0) {
|
|
||||||
return Request(kHttpPut, url, std::move(content), buffer_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool Patch(const std::string& url, std::string&& content,
|
|
||||||
std::size_t buffer_size = 0) {
|
|
||||||
return Request(kHttpPatch, url, std::move(content), buffer_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool Delete(const std::string& url, std::size_t buffer_size = 0) {
|
|
||||||
return Request(kHttpDelete, url, "", buffer_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpResponsePtr response() const {
|
HttpResponsePtr response() const {
|
||||||
return http_client_.response();
|
return http_client_base_->response();
|
||||||
}
|
}
|
||||||
|
|
||||||
int response_status() const {
|
int response_status() const {
|
||||||
@@ -73,21 +50,79 @@ class RestSslClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool timed_out() const {
|
bool timed_out() const {
|
||||||
return http_client_.timed_out();
|
return http_client_base_->timed_out();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error error() const {
|
Error error() const {
|
||||||
return http_client_.error();
|
return http_client_base_->error();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
bool Request(const std::string& method, const std::string& url,
|
// Default: "application/json".
|
||||||
std::string&& content, std::size_t buffer_size);
|
std::string content_media_type_;
|
||||||
|
// Default: "utf-8".
|
||||||
|
std::string content_charset_;
|
||||||
|
|
||||||
|
// Default headers for all session requests.
|
||||||
|
std::map<std::string, std::string> headers_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
HttpClientBase* http_client_base_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class RestSslClient : public RestClientBase {
|
||||||
|
public:
|
||||||
|
// If |port| is empty, |host| will be checked to see if it contains port or
|
||||||
|
// not (separated by ':').
|
||||||
|
explicit RestSslClient(const std::string& host,
|
||||||
|
const std::string& port = "",
|
||||||
|
bool ssl_verify = true,
|
||||||
|
const SSMap& headers = {},
|
||||||
|
std::size_t buffer_size = 0);
|
||||||
|
|
||||||
|
~RestSslClient() = default;
|
||||||
|
|
||||||
|
// NOTE:
|
||||||
|
// The return value of the following methods (Get, Post, etc.) only indicates
|
||||||
|
// if the socket communication is successful or not. Check error() and
|
||||||
|
// timed_out() for more information if it's failed. Check response_status()
|
||||||
|
// instead for the HTTP status code.
|
||||||
|
|
||||||
|
inline bool Get(const std::string& url, const SSMap& headers = {},
|
||||||
|
std::size_t buffer_size = 0) {
|
||||||
|
return Request(kHttpGet, url, "", headers, buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Post(const std::string& url, std::string&& content,
|
||||||
|
const SSMap& headers = {}, std::size_t buffer_size = 0) {
|
||||||
|
return Request(kHttpPost, url, std::move(content), headers, buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Put(const std::string& url, std::string&& content,
|
||||||
|
const SSMap& headers = {}, std::size_t buffer_size = 0) {
|
||||||
|
return Request(kHttpPut, url, std::move(content), headers, buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Patch(const std::string& url, std::string&& content,
|
||||||
|
const SSMap& headers = {}, std::size_t buffer_size = 0) {
|
||||||
|
return Request(kHttpPatch, url, std::move(content), headers, buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Delete(const std::string& url, const SSMap& headers = {},
|
||||||
|
std::size_t buffer_size = 0) {
|
||||||
|
return Request(kHttpDelete, url, "", headers, buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Request(const std::string& method, const std::string& url,
|
||||||
|
std::string&& content, const SSMap& headers = {},
|
||||||
|
std::size_t buffer_size = 0);
|
||||||
|
|
||||||
|
private:
|
||||||
std::string host_;
|
std::string host_;
|
||||||
std::string port_;
|
std::string port_;
|
||||||
|
|
||||||
HttpSslClient http_client_;
|
HttpSslClient http_ssl_client_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webcc
|
} // namespace webcc
|
||||||
|
|||||||
Reference in New Issue
Block a user