Use HttpClient as member variable inside RestClient and SoapClient.
This commit is contained in:
@@ -29,7 +29,7 @@ class BookClientBase {
|
||||
BookClientBase(const std::string& host, const std::string& port,
|
||||
int timeout_seconds)
|
||||
: rest_client_(host, port) {
|
||||
rest_client_.set_timeout_seconds(timeout_seconds);
|
||||
rest_client_.SetTimeout(timeout_seconds);
|
||||
}
|
||||
|
||||
virtual ~BookClientBase() = default;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "pugixml/pugixml.hpp"
|
||||
#include "webcc/soap_client.h"
|
||||
|
||||
#include "example/common/book.h"
|
||||
|
||||
@@ -9,7 +9,7 @@ class CalcClient {
|
||||
public:
|
||||
CalcClient(const std::string& host, const std::string& port)
|
||||
: soap_client_(host, port) {
|
||||
soap_client_.set_timeout_seconds(5);
|
||||
soap_client_.SetTimeout(5);
|
||||
|
||||
soap_client_.set_url("/calculator");
|
||||
soap_client_.set_service_ns({
|
||||
|
||||
@@ -9,7 +9,7 @@ class CalcClient {
|
||||
public:
|
||||
CalcClient(const std::string& host, const std::string& port)
|
||||
: soap_client_(host, port) {
|
||||
soap_client_.set_timeout_seconds(5);
|
||||
soap_client_.SetTimeout(5);
|
||||
|
||||
soap_client_.set_url("/glue/calculator");
|
||||
soap_client_.set_service_ns({
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace webcc {
|
||||
|
||||
HttpAsyncClient::HttpAsyncClient(boost::asio::io_context& io_context)
|
||||
: socket_(io_context),
|
||||
resolver_(new tcp::resolver(io_context)),
|
||||
resolver_(io_context),
|
||||
buffer_(kBufferSize),
|
||||
deadline_(io_context),
|
||||
timeout_seconds_(kMaxReadSeconds),
|
||||
@@ -34,11 +34,11 @@ void HttpAsyncClient::Request(std::shared_ptr<HttpRequest> request,
|
||||
request_ = request;
|
||||
response_handler_ = response_handler;
|
||||
|
||||
resolver_->async_resolve(tcp::v4(), request->host(), request->port(kHttpPort),
|
||||
std::bind(&HttpAsyncClient::ResolveHandler,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2));
|
||||
resolver_.async_resolve(tcp::v4(), request->host(), request->port(kHttpPort),
|
||||
std::bind(&HttpAsyncClient::ResolveHandler,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2));
|
||||
}
|
||||
|
||||
void HttpAsyncClient::Stop() {
|
||||
@@ -65,11 +65,8 @@ void HttpAsyncClient::ResolveHandler(boost::system::error_code ec,
|
||||
request_->host().c_str(), request_->port().c_str());
|
||||
response_handler_(response_, kHostResolveError, timed_out_);
|
||||
} else {
|
||||
// Start the connect actor.
|
||||
endpoints_ = endpoints;
|
||||
|
||||
// ConnectHandler: void(boost::system::error_code, tcp::endpoint)
|
||||
boost::asio::async_connect(socket_, endpoints_,
|
||||
boost::asio::async_connect(socket_, endpoints,
|
||||
std::bind(&HttpAsyncClient::ConnectHandler,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1,
|
||||
|
||||
@@ -19,6 +19,10 @@ namespace webcc {
|
||||
// Response handler/callback.
|
||||
typedef std::function<void(HttpResponsePtr, Error, bool)> HttpResponseHandler;
|
||||
|
||||
// HTTP client session in asynchronous mode.
|
||||
// A request will return without waiting for the response, the callback handler
|
||||
// will be invoked when the response is received or timeout occurs.
|
||||
// Don't use the same HttpAsyncClient object in multiple threads.
|
||||
class HttpAsyncClient : public std::enable_shared_from_this<HttpAsyncClient> {
|
||||
public:
|
||||
explicit HttpAsyncClient(boost::asio::io_context& io_context);
|
||||
@@ -55,9 +59,8 @@ class HttpAsyncClient : public std::enable_shared_from_this<HttpAsyncClient> {
|
||||
void AsyncWaitDeadline();
|
||||
void DeadlineHandler(boost::system::error_code ec);
|
||||
|
||||
tcp::resolver resolver_;
|
||||
tcp::socket socket_;
|
||||
std::unique_ptr<tcp::resolver> resolver_;
|
||||
tcp::resolver::results_type endpoints_;
|
||||
|
||||
std::shared_ptr<HttpRequest> request_;
|
||||
std::vector<char> buffer_;
|
||||
|
||||
@@ -27,11 +27,19 @@ HttpClient::HttpClient()
|
||||
error_(kNoError) {
|
||||
}
|
||||
|
||||
void HttpClient::SetTimeout(int seconds) {
|
||||
if (seconds > 0) {
|
||||
timeout_seconds_ = seconds;
|
||||
}
|
||||
}
|
||||
|
||||
bool HttpClient::Request(const HttpRequest& request) {
|
||||
response_.reset(new HttpResponse());
|
||||
response_parser_.reset(new HttpResponseParser(response_.get()));
|
||||
|
||||
stopped_ = timed_out_ = false;
|
||||
stopped_ = false;
|
||||
timed_out_ = false;
|
||||
error_ = kNoError;
|
||||
|
||||
if ((error_ = Connect(request)) != kNoError) {
|
||||
return false;
|
||||
|
||||
+6
-4
@@ -16,6 +16,9 @@
|
||||
|
||||
namespace webcc {
|
||||
|
||||
// HTTP client session in synchronous mode.
|
||||
// A request will not return until the response is received or timeout occurs.
|
||||
// Don't use the same HttpClient object in multiple threads.
|
||||
class HttpClient {
|
||||
public:
|
||||
HttpClient();
|
||||
@@ -23,10 +26,9 @@ class HttpClient {
|
||||
|
||||
DELETE_COPY_AND_ASSIGN(HttpClient);
|
||||
|
||||
void set_timeout_seconds(int timeout_seconds) {
|
||||
assert(timeout_seconds > 0);
|
||||
timeout_seconds_ = timeout_seconds;
|
||||
}
|
||||
// Set the timeout seconds for reading response.
|
||||
// The |seconds| is only effective when greater than 0.
|
||||
void SetTimeout(int seconds);
|
||||
|
||||
// Connect to server, send request, wait until response is received.
|
||||
bool Request(const HttpRequest& request);
|
||||
|
||||
+2
-19
@@ -1,14 +1,11 @@
|
||||
#include "webcc/rest_client.h"
|
||||
|
||||
#include "webcc/http_client.h"
|
||||
#include "webcc/http_request.h"
|
||||
|
||||
namespace webcc {
|
||||
|
||||
RestClient::RestClient(const std::string& host, const std::string& port)
|
||||
: host_(host), port_(port),
|
||||
timeout_seconds_(0), timed_out_(false),
|
||||
error_(kNoError) {
|
||||
: host_(host), port_(port) {
|
||||
if (port_.empty()) {
|
||||
std::size_t i = host_.find_last_of(':');
|
||||
if (i != std::string::npos) {
|
||||
@@ -20,11 +17,6 @@ RestClient::RestClient(const std::string& host, const std::string& port)
|
||||
|
||||
bool RestClient::Request(const std::string& method, const std::string& url,
|
||||
std::string&& content) {
|
||||
response_.reset();
|
||||
|
||||
error_ = kNoError;
|
||||
timed_out_ = false;
|
||||
|
||||
HttpRequest http_request;
|
||||
|
||||
http_request.set_method(method);
|
||||
@@ -38,19 +30,10 @@ bool RestClient::Request(const std::string& method, const std::string& url,
|
||||
|
||||
http_request.UpdateStartLine();
|
||||
|
||||
HttpClient http_client;
|
||||
|
||||
if (timeout_seconds_ > 0) {
|
||||
http_client.set_timeout_seconds(timeout_seconds_);
|
||||
}
|
||||
|
||||
if (!http_client.Request(http_request)) {
|
||||
error_ = http_client.error();
|
||||
timed_out_ = http_client.timed_out();
|
||||
if (!http_client_.Request(http_request)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
response_ = http_client.response();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+24
-22
@@ -6,6 +6,7 @@
|
||||
#include <utility> // for move()
|
||||
|
||||
#include "webcc/globals.h"
|
||||
#include "webcc/http_client.h"
|
||||
#include "webcc/http_response.h"
|
||||
|
||||
namespace webcc {
|
||||
@@ -14,20 +15,23 @@ class RestClient {
|
||||
public:
|
||||
// If |port| is empty, |host| will be checked to see if it contains port or
|
||||
// not (separated by ':').
|
||||
RestClient(const std::string& host, const std::string& port = "");
|
||||
explicit RestClient(const std::string& host, const std::string& port = "");
|
||||
|
||||
~RestClient() = default;
|
||||
|
||||
DELETE_COPY_AND_ASSIGN(RestClient);
|
||||
|
||||
void set_timeout_seconds(int timeout_seconds) {
|
||||
timeout_seconds_ = timeout_seconds;
|
||||
void SetTimeout(int seconds) {
|
||||
http_client_.SetTimeout(seconds);
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
||||
// HTTP GET request.
|
||||
// The return value indicates if the socket communication is successful
|
||||
// or not. If it's failed, check error() and timed_out() for more details.
|
||||
// For HTTP status, check response_status() instead.
|
||||
inline bool Get(const std::string& url) {
|
||||
return Request(kHttpGet, url, "");
|
||||
}
|
||||
@@ -52,21 +56,27 @@ class RestClient {
|
||||
return Request(kHttpDelete, url, "");
|
||||
}
|
||||
|
||||
HttpResponsePtr response() const { return response_; }
|
||||
HttpResponsePtr response() const {
|
||||
return http_client_.response();
|
||||
}
|
||||
|
||||
int response_status() const {
|
||||
assert(response_);
|
||||
return response_->status();
|
||||
assert(response());
|
||||
return response()->status();
|
||||
}
|
||||
|
||||
const std::string& response_content() const {
|
||||
assert(response_);
|
||||
return response_->content();
|
||||
assert(response());
|
||||
return response()->content();
|
||||
}
|
||||
|
||||
bool timed_out() const { return timed_out_; }
|
||||
bool timed_out() const {
|
||||
return http_client_.timed_out();
|
||||
}
|
||||
|
||||
Error error() const { return error_; }
|
||||
Error error() const {
|
||||
return http_client_.error();
|
||||
}
|
||||
|
||||
private:
|
||||
bool Request(const std::string& method, const std::string& url,
|
||||
@@ -75,15 +85,7 @@ class RestClient {
|
||||
std::string host_;
|
||||
std::string port_;
|
||||
|
||||
// Timeout in seconds; only effective when > 0.
|
||||
int timeout_seconds_;
|
||||
|
||||
HttpResponsePtr response_;
|
||||
|
||||
// If the error was caused by timeout or not.
|
||||
bool timed_out_;
|
||||
|
||||
Error error_;
|
||||
HttpClient http_client_;
|
||||
};
|
||||
|
||||
} // namespace webcc
|
||||
|
||||
+6
-14
@@ -3,8 +3,6 @@
|
||||
#include <cassert>
|
||||
#include <utility> // for move()
|
||||
|
||||
#include "webcc/http_client.h"
|
||||
#include "webcc/soap_globals.h"
|
||||
#include "webcc/soap_request.h"
|
||||
#include "webcc/soap_response.h"
|
||||
|
||||
@@ -13,8 +11,7 @@ namespace webcc {
|
||||
SoapClient::SoapClient(const std::string& host, const std::string& port)
|
||||
: host_(host), port_(port),
|
||||
soapenv_ns_(kSoapEnvNamespace),
|
||||
format_raw_(true), timeout_seconds_(0), timed_out_(false),
|
||||
error_(kNoError) {
|
||||
format_raw_(true), error_(kNoError) {
|
||||
if (port_.empty()) {
|
||||
std::size_t i = host_.find_last_of(':');
|
||||
if (i != std::string::npos) {
|
||||
@@ -31,6 +28,8 @@ bool SoapClient::Request(const std::string& operation,
|
||||
assert(!url_.empty() && !host_.empty());
|
||||
assert(!result_name_.empty());
|
||||
|
||||
error_ = kNoError;
|
||||
|
||||
SoapRequest soap_request;
|
||||
|
||||
soap_request.set_soapenv_ns(soapenv_ns_);
|
||||
@@ -55,22 +54,15 @@ bool SoapClient::Request(const std::string& operation,
|
||||
http_request.SetHeader(kSoapAction, operation);
|
||||
http_request.UpdateStartLine();
|
||||
|
||||
HttpClient http_client;
|
||||
|
||||
if (timeout_seconds_ > 0) {
|
||||
http_client.set_timeout_seconds(timeout_seconds_);
|
||||
}
|
||||
|
||||
if (!http_client.Request(http_request)) {
|
||||
error_ = http_client.error();
|
||||
timed_out_ = http_client.timed_out();
|
||||
if (!http_client_.Request(http_request)) {
|
||||
error_ = http_client_.error();
|
||||
return false;
|
||||
}
|
||||
|
||||
SoapResponse soap_response;
|
||||
soap_response.set_result_name(result_name_);
|
||||
|
||||
if (!soap_response.FromXml(http_client.response()->content())) {
|
||||
if (!soap_response.FromXml(http_client_.response()->content())) {
|
||||
error_ = kXmlError;
|
||||
return false;
|
||||
}
|
||||
|
||||
+12
-11
@@ -4,7 +4,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "webcc/soap_message.h"
|
||||
#include "webcc/http_client.h"
|
||||
#include "webcc/soap_globals.h"
|
||||
#include "webcc/soap_parameter.h"
|
||||
|
||||
namespace webcc {
|
||||
@@ -13,14 +14,14 @@ class SoapClient {
|
||||
public:
|
||||
// If |port| is empty, |host| will be checked to see if it contains port or
|
||||
// not (separated by ':').
|
||||
SoapClient(const std::string& host, const std::string& port = "");
|
||||
explicit SoapClient(const std::string& host, const std::string& port = "");
|
||||
|
||||
~SoapClient() = default;
|
||||
|
||||
DELETE_COPY_AND_ASSIGN(SoapClient);
|
||||
|
||||
void set_timeout_seconds(int timeout_seconds) {
|
||||
timeout_seconds_ = timeout_seconds;
|
||||
void SetTimeout(int seconds) {
|
||||
http_client_.SetTimeout(seconds);
|
||||
}
|
||||
|
||||
void set_url(const std::string& url) { url_ = url; }
|
||||
@@ -33,7 +34,9 @@ class SoapClient {
|
||||
result_name_ = result_name;
|
||||
}
|
||||
|
||||
void set_format_raw(bool format_raw) { format_raw_ = format_raw; }
|
||||
void set_format_raw(bool format_raw) {
|
||||
format_raw_ = format_raw;
|
||||
}
|
||||
|
||||
void set_indent_str(const std::string& indent_str) {
|
||||
indent_str_ = indent_str;
|
||||
@@ -43,7 +46,9 @@ class SoapClient {
|
||||
std::vector<SoapParameter>&& parameters,
|
||||
std::string* result);
|
||||
|
||||
bool timed_out() const { return timed_out_; }
|
||||
bool timed_out() const {
|
||||
return http_client_.timed_out();
|
||||
}
|
||||
|
||||
Error error() const { return error_; }
|
||||
|
||||
@@ -68,11 +73,7 @@ class SoapClient {
|
||||
// Applicable when |format_raw_| is false.
|
||||
std::string indent_str_;
|
||||
|
||||
// Timeout in seconds; only effective when > 0.
|
||||
int timeout_seconds_;
|
||||
|
||||
// If the error was caused by timeout or not.
|
||||
bool timed_out_;
|
||||
HttpClient http_client_;
|
||||
|
||||
Error error_;
|
||||
};
|
||||
|
||||
@@ -10,4 +10,9 @@ const std::string kSoapAction = "SOAPAction";
|
||||
// See: https://www.w3.org/TR/2007/REC-soap12-part0-20070427/#L26854
|
||||
const std::string kTextXmlUtf8 = "text/xml; charset=utf-8";
|
||||
|
||||
const SoapNamespace kSoapEnvNamespace{
|
||||
"soap",
|
||||
"http://schemas.xmlsoap.org/soap/envelope/"
|
||||
};
|
||||
|
||||
} // namespace webcc
|
||||
|
||||
@@ -12,6 +12,22 @@ extern const std::string kSoapAction;
|
||||
|
||||
extern const std::string kTextXmlUtf8;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// XML namespace name/url pair.
|
||||
// E.g., { "soap", "http://schemas.xmlsoap.org/soap/envelope/" }
|
||||
struct SoapNamespace {
|
||||
std::string name;
|
||||
std::string url;
|
||||
|
||||
bool IsValid() const {
|
||||
return !name.empty() && !url.empty();
|
||||
}
|
||||
};
|
||||
|
||||
// CSoap's default namespace for SOAP Envelope.
|
||||
extern const SoapNamespace kSoapEnvNamespace;
|
||||
|
||||
} // namespace webcc
|
||||
|
||||
#endif // WEBCC_SOAP_GLOBALS_H_
|
||||
|
||||
@@ -6,11 +6,6 @@
|
||||
|
||||
namespace webcc {
|
||||
|
||||
const SoapNamespace kSoapEnvNamespace{
|
||||
"soap",
|
||||
"http://schemas.xmlsoap.org/soap/envelope/"
|
||||
};
|
||||
|
||||
void SoapMessage::ToXml(bool format_raw, const std::string& indent,
|
||||
std::string* xml_string) {
|
||||
assert(soapenv_ns_.IsValid() && service_ns_.IsValid() && !operation_.empty());
|
||||
|
||||
+2
-16
@@ -5,28 +5,14 @@
|
||||
|
||||
#include "pugixml/pugixml.hpp"
|
||||
|
||||
#include "webcc/globals.h"
|
||||
#include "webcc/soap_globals.h"
|
||||
|
||||
namespace webcc {
|
||||
|
||||
// XML namespace name/url pair.
|
||||
// E.g., { "soap", "http://schemas.xmlsoap.org/soap/envelope/" }
|
||||
struct SoapNamespace {
|
||||
std::string name;
|
||||
std::string url;
|
||||
|
||||
bool IsValid() const {
|
||||
return !name.empty() && !url.empty();
|
||||
}
|
||||
};
|
||||
|
||||
// CSoap's default namespace for SOAP Envelope.
|
||||
extern const SoapNamespace kSoapEnvNamespace;
|
||||
|
||||
// Base class for SOAP request and response.
|
||||
class SoapMessage {
|
||||
public:
|
||||
virtual ~SoapMessage() {}
|
||||
virtual ~SoapMessage() = default;
|
||||
|
||||
// E.g., set as kSoapEnvNamespace.
|
||||
void set_soapenv_ns(const SoapNamespace& soapenv_ns) {
|
||||
|
||||
Reference in New Issue
Block a user