Initial client API V2
parent
b38b7e6d38
commit
9b8304f06c
@ -1,29 +1,49 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "webcc/http_client.h"
|
#include "webcc/http_client_session.h" // TEST
|
||||||
#include "webcc/logger.h"
|
#include "webcc/logger.h"
|
||||||
|
|
||||||
static void PrintError(const webcc::HttpClient& client) {
|
|
||||||
std::cout << webcc::DescribeError(client.error());
|
|
||||||
if (client.timed_out()) {
|
|
||||||
std::cout << " (timed out)";
|
|
||||||
}
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
WEBCC_LOG_INIT("", webcc::LOG_CONSOLE);
|
WEBCC_LOG_INIT("", webcc::LOG_CONSOLE);
|
||||||
|
|
||||||
auto request = webcc::HttpRequest::New(webcc::kHttpGet, "/get",
|
using namespace webcc;
|
||||||
"httpbin.org");
|
|
||||||
|
HttpResponsePtr r;
|
||||||
|
|
||||||
|
HttpClientSession session;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
r = session.Request(HttpRequestArgs("GET")
|
||||||
|
.url("http://httpbin.org/get") // Moved
|
||||||
|
.parameters({ "key1", "value1", "key2", "value2" }) // Moved
|
||||||
|
.headers({ "Accept", "application/json" }) // Moved
|
||||||
|
.buffer_size(1000));
|
||||||
|
|
||||||
|
std::cout << r->content() << std::endl;
|
||||||
|
|
||||||
|
// If you want to create the args object firstly, there'll be an extra call
|
||||||
|
// to its move constructor.
|
||||||
|
// - constructor: HttpRequestArgs("GET")
|
||||||
|
// - move constructor: auto args = ...
|
||||||
|
auto args = HttpRequestArgs("GET")
|
||||||
|
.url("http://httpbin.org/get")
|
||||||
|
.parameters({ "key1", "value1", "key2", "value2" })
|
||||||
|
.headers({ "Accept", "application/json" })
|
||||||
|
.buffer_size(1000);
|
||||||
|
|
||||||
|
r = session.Request(std::move(args));
|
||||||
|
|
||||||
|
r = session.Get("http://httpbin.org/get",
|
||||||
|
{ "key1", "value1", "key2", "value2" },
|
||||||
|
{ "Accept", "application/json" },
|
||||||
|
HttpRequestArgs().buffer_size(1000));
|
||||||
|
#endif
|
||||||
|
|
||||||
webcc::HttpClient client;
|
r = session.Post("http://httpbin.org/post", "{ 'key': 'value' }", true,
|
||||||
|
{ "Accept", "application/json" },
|
||||||
|
HttpRequestArgs().buffer_size(1000));
|
||||||
|
|
||||||
if (client.Request(*request)) {
|
std::cout << r->content() << std::endl;
|
||||||
std::cout << client.response_content() << std::endl;
|
|
||||||
} else {
|
|
||||||
PrintError(client);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,80 @@
|
|||||||
|
#include "webcc/http_client_session.h"
|
||||||
|
|
||||||
|
#include "webcc/http_client.h"
|
||||||
|
#include "webcc/http_request.h"
|
||||||
|
#include "webcc/url.h"
|
||||||
|
|
||||||
|
namespace webcc {
|
||||||
|
|
||||||
|
HttpClientSession::HttpClientSession() {
|
||||||
|
InitHeaders();
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpResponsePtr HttpClientSession::Request(HttpRequestArgs&& args) {
|
||||||
|
assert(args.parameters_.size() % 2 == 0);
|
||||||
|
assert(args.headers_.size() % 2 == 0);
|
||||||
|
|
||||||
|
HttpRequest request(args.method_, args.url_, args.parameters_);
|
||||||
|
|
||||||
|
if (!args.data_.empty()) {
|
||||||
|
request.SetContent(std::move(args.data_), true);
|
||||||
|
|
||||||
|
// TODO: charset/encoding
|
||||||
|
if (args.json_) {
|
||||||
|
request.SetContentType(http::media_types::kApplicationJson, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the session-level headers.
|
||||||
|
for (const HttpHeader& h : headers_.data()) {
|
||||||
|
request.SetHeader(h.first, h.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the request-level headers.
|
||||||
|
// This will overwrite the session-level headers.
|
||||||
|
for (std::size_t i = 1; i < args.headers_.size(); i += 2) {
|
||||||
|
request.SetHeader(std::move(args.headers_[i - 1]),
|
||||||
|
std::move(args.headers_[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
request.Prepare();
|
||||||
|
|
||||||
|
HttpClient client;
|
||||||
|
if (!client.Request(request, args.buffer_size_)) {
|
||||||
|
return HttpResponsePtr{};
|
||||||
|
}
|
||||||
|
|
||||||
|
return client.response();
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpResponsePtr HttpClientSession::Get(const std::string& url,
|
||||||
|
std::vector<std::string>&& parameters,
|
||||||
|
std::vector<std::string>&& headers,
|
||||||
|
HttpRequestArgs&& args) {
|
||||||
|
return Request(args.method(http::kGet).url(url)
|
||||||
|
.parameters(std::move(parameters))
|
||||||
|
.headers(std::move(headers)));
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpResponsePtr HttpClientSession::Post(const std::string& url,
|
||||||
|
std::string&& data, bool json,
|
||||||
|
std::vector<std::string>&& headers,
|
||||||
|
HttpRequestArgs&& args) {
|
||||||
|
return Request(args.method(http::kPost).url(url).data(std::move(data))
|
||||||
|
.json(json).headers(std::move(headers)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpClientSession::InitHeaders() {
|
||||||
|
// NOTE: C++11 requires a space between literal and string macro.
|
||||||
|
headers_.Add(http::headers::kUserAgent, USER_AGENT);
|
||||||
|
|
||||||
|
// TODO: Support gzip, deflate
|
||||||
|
headers_.Add(http::headers::kAcceptEncoding, "identity");
|
||||||
|
|
||||||
|
headers_.Add(http::headers::kAccept, "*/*");
|
||||||
|
|
||||||
|
// TODO: Support Keep-Alive connection.
|
||||||
|
//headers_.Add(http::headers::kConnection, "close");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webcc
|
@ -0,0 +1,43 @@
|
|||||||
|
#ifndef WEBCC_HTTP_CLIENT_SESSION_H_
|
||||||
|
#define WEBCC_HTTP_CLIENT_SESSION_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "webcc/http_request_args.h"
|
||||||
|
#include "webcc/http_response.h"
|
||||||
|
|
||||||
|
namespace webcc {
|
||||||
|
|
||||||
|
class HttpClientSession {
|
||||||
|
public:
|
||||||
|
HttpClientSession();
|
||||||
|
|
||||||
|
~HttpClientSession() = default;
|
||||||
|
|
||||||
|
void AddHeader(const std::string& key, const std::string& value) {
|
||||||
|
headers_.Add(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpResponsePtr Request(HttpRequestArgs&& args);
|
||||||
|
|
||||||
|
HttpResponsePtr Get(const std::string& url,
|
||||||
|
std::vector<std::string>&& parameters = {},
|
||||||
|
std::vector<std::string>&& headers = {},
|
||||||
|
HttpRequestArgs&& args = HttpRequestArgs());
|
||||||
|
|
||||||
|
HttpResponsePtr Post(const std::string& url,
|
||||||
|
std::string&& data, bool json,
|
||||||
|
std::vector<std::string>&& headers = {},
|
||||||
|
HttpRequestArgs&& args = HttpRequestArgs());
|
||||||
|
|
||||||
|
private:
|
||||||
|
void InitHeaders();
|
||||||
|
|
||||||
|
// Headers to be sent on each request sent from this session.
|
||||||
|
HttpHeaderDict headers_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace webcc
|
||||||
|
|
||||||
|
#endif // WEBCC_HTTP_CLIENT_SESSION_H_
|
@ -0,0 +1,140 @@
|
|||||||
|
#ifndef WEBCC_HTTP_REQUEST_ARGS_H_
|
||||||
|
#define WEBCC_HTTP_REQUEST_ARGS_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "webcc/globals.h"
|
||||||
|
#include "webcc/logger.h"
|
||||||
|
|
||||||
|
namespace webcc {
|
||||||
|
|
||||||
|
class HttpClientSession;
|
||||||
|
|
||||||
|
// Args maker for HttpClientSession.
|
||||||
|
// Use method chaining to simulate Named Parameters.
|
||||||
|
class HttpRequestArgs {
|
||||||
|
public:
|
||||||
|
explicit HttpRequestArgs(const std::string& method = "")
|
||||||
|
: method_(method), json_(false), buffer_size_(0) {
|
||||||
|
LOG_VERB("HttpRequestArgs()");
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpRequestArgs(const HttpRequestArgs&) = default;
|
||||||
|
HttpRequestArgs& operator=(const HttpRequestArgs&) = default;
|
||||||
|
|
||||||
|
#if WEBCC_DEFAULT_MOVE_COPY_ASSIGN
|
||||||
|
|
||||||
|
HttpRequestArgs(HttpRequestArgs&&) = default;
|
||||||
|
HttpRequestArgs& operator=(HttpRequestArgs&&) = default;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
HttpRequestArgs(HttpRequestArgs&& rhs)
|
||||||
|
: method_(std::move(rhs.method_)),
|
||||||
|
url_(std::move(rhs.url_)),
|
||||||
|
parameters_(std::move(rhs.parameters_)),
|
||||||
|
data_(std::move(rhs.data_)),
|
||||||
|
json_(rhs.json_),
|
||||||
|
headers_(std::move(rhs.headers_)),
|
||||||
|
buffer_size_(rhs.buffer_size_) {
|
||||||
|
LOG_VERB("HttpRequestArgs(&&)");
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpRequestArgs& operator=(HttpRequestArgs&& rhs) {
|
||||||
|
if (&rhs != this) {
|
||||||
|
method_ = std::move(rhs.method_);
|
||||||
|
url_ = std::move(rhs.url_);
|
||||||
|
parameters_ = std::move(rhs.parameters_);
|
||||||
|
data_ = std::move(rhs.data_);
|
||||||
|
json_ = rhs.json_;
|
||||||
|
headers_ = std::move(rhs.headers_);
|
||||||
|
buffer_size_ = buffer_size_;
|
||||||
|
}
|
||||||
|
LOG_VERB("HttpRequestArgs& operator=(&&)");
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // WEBCC_DEFAULT_MOVE_COPY_ASSIGN
|
||||||
|
|
||||||
|
HttpRequestArgs&& method(const std::string& method) {
|
||||||
|
method_ = method;
|
||||||
|
return std::move(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpRequestArgs&& url(const std::string& url) {
|
||||||
|
url_ = url;
|
||||||
|
return std::move(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpRequestArgs&& url(std::string&& url) {
|
||||||
|
url_ = std::move(url);
|
||||||
|
return std::move(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpRequestArgs&& parameters(const std::vector<std::string>& parameters) {
|
||||||
|
parameters_ = parameters;
|
||||||
|
return std::move(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpRequestArgs&& parameters(std::vector<std::string>&& parameters) {
|
||||||
|
parameters_ = std::move(parameters);
|
||||||
|
return std::move(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpRequestArgs&& data(const std::string& data) {
|
||||||
|
data_ = data;
|
||||||
|
return std::move(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpRequestArgs&& data(std::string&& data) {
|
||||||
|
data_ = std::move(data);
|
||||||
|
return std::move(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpRequestArgs&& json(bool json = true) {
|
||||||
|
json_ = json;
|
||||||
|
return std::move(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpRequestArgs&& headers(const std::vector<std::string>& headers) {
|
||||||
|
headers_ = headers;
|
||||||
|
return std::move(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpRequestArgs&& headers(std::vector<std::string>&& headers) {
|
||||||
|
headers_ = std::move(headers);
|
||||||
|
return std::move(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpRequestArgs&& buffer_size(std::size_t buffer_size) {
|
||||||
|
buffer_size_ = buffer_size;
|
||||||
|
return std::move(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class HttpClientSession;
|
||||||
|
|
||||||
|
std::string method_;
|
||||||
|
|
||||||
|
std::string url_;
|
||||||
|
|
||||||
|
std::vector<std::string> parameters_;
|
||||||
|
|
||||||
|
// Data to send in the body of the request.
|
||||||
|
std::string data_;
|
||||||
|
|
||||||
|
// Is the data to send a JSON string?
|
||||||
|
bool json_;
|
||||||
|
|
||||||
|
std::vector<std::string> headers_;
|
||||||
|
|
||||||
|
// Size of the buffer to read response.
|
||||||
|
// Leave it to 0 for using default value.
|
||||||
|
std::size_t buffer_size_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace webcc
|
||||||
|
|
||||||
|
#endif // WEBCC_HTTP_REQUEST_ARGS_H_
|
Loading…
Reference in New Issue