Use composite instead of inheritance for SoapClient.

master
Adam Gu 7 years ago
parent 223e59cc7a
commit 6475a3fd35

@ -13,14 +13,14 @@ static void PrintSeparateLine() {
} }
BookClient::BookClient(const std::string& host, const std::string& port) BookClient::BookClient(const std::string& host, const std::string& port)
: webcc::SoapClient(host, port), code_(0) { : soap_client_(host, port), code_(0) {
url_ = "/book"; soap_client_.set_url("/book");
service_ns_ = { "ser", "http://www.example.com/book/" }; soap_client_.set_service_ns({ "ser", "http://www.example.com/book/" });
result_name_ = "Result"; soap_client_.set_result_name("Result");
// Customize response XML format. // Customize response XML format.
format_raw_ = false; soap_client_.set_format_raw(false);
indent_str_ = " "; soap_client_.set_indent_str(" ");
} }
bool BookClient::CreateBook(const std::string& title, double price, std::string* id) { bool BookClient::CreateBook(const std::string& title, double price, std::string* id) {
@ -87,7 +87,7 @@ bool BookClient::DeleteBook(const std::string& id) {
} }
bool BookClient::Call0(const std::string& operation, std::string* result_str) { bool BookClient::Call0(const std::string& operation, std::string* result_str) {
return CallX(operation, {}, result_str); return Call(operation, {}, result_str);
} }
@ -96,25 +96,27 @@ bool BookClient::Call1(const std::string& operation, webcc::SoapParameter&& para
std::vector<webcc::SoapParameter> parameters{ std::vector<webcc::SoapParameter> parameters{
{ std::move(parameter) } { std::move(parameter) }
}; };
return CallX(operation, std::move(parameters), result_str); return Call(operation, std::move(parameters), result_str);
} }
bool BookClient::CallX(const std::string& operation, bool BookClient::Call(const std::string& operation,
std::vector<webcc::SoapParameter>&& parameters, std::vector<webcc::SoapParameter>&& parameters,
std::string* result_str) { std::string* result_str) {
webcc::Error error = webcc::SoapClient::Call(operation, if (!soap_client_.Request(operation, std::move(parameters), result_str)) {
std::move(parameters), PrintError();
result_str);
if (error != webcc::kNoError) {
LOG_ERRO("Operation '%s' failed: %s",
operation, webcc::DescribeError(error));
return false; return false;
} }
return true; return true;
} }
void BookClient::PrintError() {
std::cout << webcc::DescribeError(soap_client_.error());
if (soap_client_.timed_out()) {
std::cout << " (timed out)";
}
std::cout << std::endl;
}
bool BookClient::ParseResultXml(const std::string& result_xml, bool BookClient::ParseResultXml(const std::string& result_xml,
std::function<bool(pugi::xml_node)> callback) { std::function<bool(pugi::xml_node)> callback) {
pugi::xml_document xdoc; pugi::xml_document xdoc;

@ -8,12 +8,10 @@
#include "example/common/book.h" #include "example/common/book.h"
class BookClient : public webcc::SoapClient { class BookClient {
public: public:
BookClient(const std::string& host, const std::string& port); BookClient(const std::string& host, const std::string& port);
~BookClient() override = default;
int code() const { return code_; } int code() const { return code_; }
const std::string& message() const { return message_; } const std::string& message() const { return message_; }
@ -37,14 +35,18 @@ class BookClient : public webcc::SoapClient {
bool Call1(const std::string& operation, webcc::SoapParameter&& parameter, bool Call1(const std::string& operation, webcc::SoapParameter&& parameter,
std::string* result_str); std::string* result_str);
// Simple wrapper of webcc::SoapClient::Call() to log error if any. // Simple wrapper of SoapClient::Request() to log error if any.
bool CallX(const std::string& operation, bool Call(const std::string& operation,
std::vector<webcc::SoapParameter>&& parameters, std::vector<webcc::SoapParameter>&& parameters,
std::string* result_str); std::string* result_str);
void PrintError();
bool ParseResultXml(const std::string& result_xml, bool ParseResultXml(const std::string& result_xml,
std::function<bool(pugi::xml_node)> callback); std::function<bool(pugi::xml_node)> callback);
webcc::SoapClient soap_client_;
// Last status. // Last status.
int code_; int code_;
std::string message_; std::string message_;

@ -5,19 +5,21 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
class CalcClient : public webcc::SoapClient { class CalcClient {
public: public:
CalcClient(const std::string& host, const std::string& port) CalcClient(const std::string& host, const std::string& port)
: webcc::SoapClient(host, port) { : soap_client_(host, port) {
timeout_seconds_ = 5; // Override the default timeout. soap_client_.set_timeout_seconds(5);
url_ = "/calculator"; soap_client_.set_url("/calculator");
service_ns_ = { "ser", "http://www.example.com/calculator/" }; soap_client_.set_service_ns({
result_name_ = "Result"; "ser", "http://www.example.com/calculator/"
});
soap_client_.set_result_name("Result");
// Customize request XML format. // Customize request XML format.
format_raw_ = false; soap_client_.set_format_raw(false);
indent_str_ = " "; soap_client_.set_indent_str(" ");
} }
bool Add(double x, double y, double* result) { bool Add(double x, double y, double* result) {
@ -41,7 +43,7 @@ class CalcClient : public webcc::SoapClient {
return Calc("unknown", "x", "y", x, y, result); return Calc("unknown", "x", "y", x, y, result);
} }
protected: private:
bool Calc(const std::string& operation, bool Calc(const std::string& operation,
const std::string& x_name, const std::string& y_name, const std::string& x_name, const std::string& y_name,
double x, double y, double x, double y,
@ -52,11 +54,8 @@ class CalcClient : public webcc::SoapClient {
}; };
std::string result_str; std::string result_str;
webcc::Error error = Call(operation, std::move(parameters), &result_str); if (!soap_client_.Request(operation, std::move(parameters), &result_str)) {
PrintError();
if (error != webcc::kNoError) {
LOG_ERRO("Operation '%s' failed: %s", operation.c_str(),
webcc::DescribeError(error));
return false; return false;
} }
@ -68,6 +67,16 @@ class CalcClient : public webcc::SoapClient {
return true; return true;
} }
void PrintError() {
std::cout << webcc::DescribeError(soap_client_.error());
if (soap_client_.timed_out()) {
std::cout << " (timed out)";
}
std::cout << std::endl;
}
webcc::SoapClient soap_client_;
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

@ -5,19 +5,21 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
class CalcClient : public webcc::SoapClient { class CalcClient {
public: public:
CalcClient(const std::string& host, const std::string& port) CalcClient(const std::string& host, const std::string& port)
: webcc::SoapClient(host, port) { : soap_client_(host, port) {
timeout_seconds_ = 5; // Override the default timeout. soap_client_.set_timeout_seconds(5);
url_ = "/glue/calculator"; soap_client_.set_url("/glue/calculator");
service_ns_ = { "cal", "http://www.parasoft.com/wsdl/calculator/" }; soap_client_.set_service_ns({
result_name_ = "Result"; "cal", "http://www.parasoft.com/wsdl/calculator/"
});
soap_client_.set_result_name("Result");
// Customize request XML format. // Customize request XML format.
format_raw_ = false; soap_client_.set_format_raw(false);
indent_str_ = " "; soap_client_.set_indent_str(" ");
} }
bool Add(double x, double y, double* result) { bool Add(double x, double y, double* result) {
@ -36,7 +38,7 @@ class CalcClient : public webcc::SoapClient {
return Calc("divide", "numerator", "denominator", x, y, result); return Calc("divide", "numerator", "denominator", x, y, result);
} }
protected: private:
bool Calc(const std::string& operation, bool Calc(const std::string& operation,
const std::string& x_name, const std::string& y_name, const std::string& x_name, const std::string& y_name,
double x, double y, double x, double y,
@ -47,11 +49,8 @@ class CalcClient : public webcc::SoapClient {
}; };
std::string result_str; std::string result_str;
webcc::Error error = Call(operation, std::move(parameters), &result_str); if (!soap_client_.Request(operation, std::move(parameters), &result_str)) {
PrintError();
if (error != webcc::kNoError) {
LOG_ERRO("Operation '%s' failed: %s", operation.c_str(),
webcc::DescribeError(error));
return false; return false;
} }
@ -63,6 +62,16 @@ class CalcClient : public webcc::SoapClient {
return true; return true;
} }
void PrintError() {
std::cout << webcc::DescribeError(soap_client_.error());
if (soap_client_.timed_out()) {
std::cout << " (timed out)";
}
std::cout << std::endl;
}
webcc::SoapClient soap_client_;
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

@ -6,10 +6,8 @@
namespace webcc { namespace webcc {
RestClient::RestClient(const std::string& host, const std::string& port) RestClient::RestClient(const std::string& host, const std::string& port)
: host_(host), : host_(host), port_(port),
port_(port), timeout_seconds_(0), timed_out_(false),
timeout_seconds_(0),
timed_out_(false),
error_(kNoError) { error_(kNoError) {
} }
@ -20,18 +18,18 @@ bool RestClient::Request(const std::string& method, const std::string& url,
error_ = kNoError; error_ = kNoError;
timed_out_ = false; timed_out_ = false;
HttpRequest request; HttpRequest http_request;
request.set_method(method); http_request.set_method(method);
request.set_url(url); http_request.set_url(url);
request.SetHost(host_, port_); http_request.SetHost(host_, port_);
if (!content.empty()) { if (!content.empty()) {
request.SetContent(std::move(content), true); http_request.SetContent(std::move(content), true);
request.SetContentType(kAppJsonUtf8); http_request.SetContentType(kAppJsonUtf8);
} }
request.UpdateStartLine(); http_request.UpdateStartLine();
HttpClient http_client; HttpClient http_client;
@ -39,7 +37,7 @@ bool RestClient::Request(const std::string& method, const std::string& url,
http_client.set_timeout_seconds(timeout_seconds_); http_client.set_timeout_seconds(timeout_seconds_);
} }
if (!http_client.Request(request)) { if (!http_client.Request(http_request)) {
error_ = http_client.error(); error_ = http_client.error();
timed_out_ = http_client.timed_out(); timed_out_ = http_client.timed_out();
return false; return false;

@ -13,20 +13,18 @@ namespace webcc {
SoapClient::SoapClient(const std::string& host, const std::string& port) SoapClient::SoapClient(const std::string& host, const std::string& port)
: host_(host), port_(port), : host_(host), port_(port),
format_raw_(true), timeout_seconds_(0), timed_out_(false) { soapenv_ns_(kSoapEnvNamespace),
format_raw_(true), timeout_seconds_(0), timed_out_(false),
error_(kNoError) {
} }
Error SoapClient::Call(const std::string& operation, bool SoapClient::Request(const std::string& operation,
std::vector<SoapParameter>&& parameters, std::vector<SoapParameter>&& parameters,
std::string* result) { std::string* result) {
assert(service_ns_.IsValid()); assert(service_ns_.IsValid());
assert(!url_.empty() && !host_.empty()); assert(!url_.empty() && !host_.empty());
assert(!result_name_.empty()); assert(!result_name_.empty());
if (!soapenv_ns_.IsValid()) {
soapenv_ns_ = kSoapEnvNamespace;
}
SoapRequest soap_request; SoapRequest soap_request;
soap_request.set_soapenv_ns(soapenv_ns_); soap_request.set_soapenv_ns(soapenv_ns_);
@ -58,20 +56,22 @@ Error SoapClient::Call(const std::string& operation,
} }
if (!http_client.Request(http_request)) { if (!http_client.Request(http_request)) {
error_ = http_client.error();
timed_out_ = http_client.timed_out(); timed_out_ = http_client.timed_out();
return http_client.error(); return false;
} }
SoapResponse soap_response; SoapResponse soap_response;
soap_response.set_result_name(result_name_); soap_response.set_result_name(result_name_);
if (!soap_response.FromXml(http_client.response()->content())) { if (!soap_response.FromXml(http_client.response()->content())) {
return kXmlError; error_ = kXmlError;
return false;
} }
*result = soap_response.result_moved(); *result = soap_response.result_moved();
return kNoError; return true;
} }
} // namespace webcc } // namespace webcc

@ -9,13 +9,27 @@
namespace webcc { namespace webcc {
// Base class for your SOAP client.
// Set URL, host, port, etc. in your sub-class before make the call.
class SoapClient { class SoapClient {
public: public:
virtual ~SoapClient() = default; SoapClient(const std::string& host, const std::string& port);
bool timed_out() const { return timed_out_; } ~SoapClient() = default;
DELETE_COPY_AND_ASSIGN(SoapClient);
void set_timeout_seconds(int timeout_seconds) {
timeout_seconds_ = timeout_seconds;
}
void set_url(const std::string& url) { url_ = url; }
void set_service_ns(const SoapNamespace& service_ns) {
service_ns_ = service_ns;
}
void set_result_name(const std::string& result_name) {
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; }
@ -23,23 +37,23 @@ class SoapClient {
indent_str_ = indent_str; indent_str_ = indent_str;
} }
protected: bool timed_out() const { return timed_out_; }
SoapClient(const std::string& host, const std::string& port);
// A generic wrapper to make a call. Error error() const { return error_; }
// NOTE: The parameters should be movable.
Error Call(const std::string& operation,
std::vector<SoapParameter>&& parameters,
std::string* result);
SoapNamespace soapenv_ns_; // SOAP envelope namespace. bool Request(const std::string& operation,
SoapNamespace service_ns_; // Namespace for your web service. std::vector<SoapParameter>&& parameters,
std::string* result);
private:
std::string host_;
std::string port_; // Leave this empty to use default 80.
// Request URL. // Request URL.
std::string url_; std::string url_;
std::string host_; SoapNamespace soapenv_ns_; // SOAP envelope namespace.
std::string port_; // Leave this empty to use default 80. SoapNamespace service_ns_; // Namespace for your web service.
// Response result XML node name. // Response result XML node name.
// E.g., "Result". // E.g., "Result".
@ -57,6 +71,8 @@ class SoapClient {
// If the error was caused by timeout or not. // If the error was caused by timeout or not.
bool timed_out_; bool timed_out_;
Error error_;
}; };
} // namespace webcc } // namespace webcc

Loading…
Cancel
Save