Add SoapAsyncClient.

master
Adam Gu 7 years ago
parent 6809ab7d2a
commit ab781a691f

@ -2,8 +2,8 @@
#include "json/json.h" #include "json/json.h"
#include "webcc/rest_async_client.h"
#include "webcc/logger.h" #include "webcc/logger.h"
#include "webcc/rest_async_client.h"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -50,7 +50,7 @@ class BookListClient {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
class BookDetailClient { class BookDetailClient {
public: public:
BookDetailClient(boost::asio::io_context& io_context, BookDetailClient(boost::asio::io_context& io_context,
const std::string& host, const std::string& port) const std::string& host, const std::string& port)
: rest_client_(io_context, host, port) { : rest_client_(io_context, host, port) {
@ -83,7 +83,7 @@ public:
rest_client_.Delete("/book/" + id, handler); rest_client_.Delete("/book/" + id, handler);
} }
private: private:
webcc::RestAsyncClient rest_client_; webcc::RestAsyncClient rest_client_;
}; };
@ -112,8 +112,7 @@ int main(int argc, char* argv[]) {
BookDetailClient detail_client(io_context, host, port); BookDetailClient detail_client(io_context, host, port);
// Response handler. // Response handler.
auto handler = [](std::shared_ptr<webcc::HttpResponse> response, auto handler = [](webcc::HttpResponsePtr response, webcc::Error error,
webcc::Error error,
bool timed_out) { bool timed_out) {
if (error == webcc::kNoError) { if (error == webcc::kNoError) {
std::cout << response->content() << std::endl; std::cout << response->content() << std::endl;

@ -23,7 +23,8 @@ BookClient::BookClient(const std::string& host, const std::string& port)
soap_client_.set_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) {
PrintSeparateLine(); PrintSeparateLine();
std::cout << "CreateBook: " << title << ", " << price << std::endl; std::cout << "CreateBook: " << title << ", " << price << std::endl;
@ -91,7 +92,8 @@ bool BookClient::Call0(const std::string& operation, std::string* result_str) {
} }
bool BookClient::Call1(const std::string& operation, webcc::SoapParameter&& parameter, bool BookClient::Call1(const std::string& operation,
webcc::SoapParameter&& parameter,
std::string* result_str) { std::string* result_str) {
std::vector<webcc::SoapParameter> parameters{ std::vector<webcc::SoapParameter> parameters{
{ std::move(parameter) } { std::move(parameter) }

@ -65,6 +65,7 @@ endif()
if(WEBCC_ENABLE_SOAP) if(WEBCC_ENABLE_SOAP)
set(SOAP_HEADERS set(SOAP_HEADERS
soap_async_client.h
soap_client.h soap_client.h
soap_message.h soap_message.h
soap_parameter.h soap_parameter.h
@ -77,6 +78,7 @@ if(WEBCC_ENABLE_SOAP)
) )
set(SOAP_SOURCES set(SOAP_SOURCES
soap_async_client.cc
soap_client.cc soap_client.cc
soap_message.cc soap_message.cc
soap_response.cc soap_response.cc

@ -16,7 +16,7 @@
namespace webcc { namespace webcc {
// Request handler/callback. // Response handler/callback.
typedef std::function<void(HttpResponsePtr, Error, bool)> HttpResponseHandler; typedef std::function<void(HttpResponsePtr, Error, bool)> HttpResponseHandler;
class HttpAsyncClient : public std::enable_shared_from_this<HttpAsyncClient> { class HttpAsyncClient : public std::enable_shared_from_this<HttpAsyncClient> {

@ -12,8 +12,6 @@ void RestAsyncClient::Request(const std::string& method,
const std::string& url, const std::string& url,
std::string&& content, std::string&& content,
HttpResponseHandler response_handler) { HttpResponseHandler response_handler) {
response_handler_ = response_handler;
HttpRequestPtr request(new webcc::HttpRequest()); HttpRequestPtr request(new webcc::HttpRequest());
request->set_method(method); request->set_method(method);
@ -33,7 +31,7 @@ void RestAsyncClient::Request(const std::string& method,
http_client->set_timeout_seconds(timeout_seconds_); http_client->set_timeout_seconds(timeout_seconds_);
} }
http_client->Request(request, response_handler_); http_client->Request(request, response_handler);
} }
} // namespace webcc } // namespace webcc

@ -51,8 +51,6 @@ class RestAsyncClient {
std::string host_; std::string host_;
std::string port_; std::string port_;
HttpResponseHandler response_handler_;
// Timeout in seconds; only effective when > 0. // Timeout in seconds; only effective when > 0.
int timeout_seconds_; int timeout_seconds_;
}; };

@ -24,21 +24,7 @@ class RestClient {
timeout_seconds_ = timeout_seconds; timeout_seconds_ = timeout_seconds;
} }
HttpResponsePtr response() const { return response_; } // Requests
int response_status() const {
assert(response_);
return response_->status();
}
const std::string& response_content() const {
assert(response_);
return response_->content();
}
bool timed_out() const { return timed_out_; }
Error error() const { return error_; }
inline bool Get(const std::string& url) { inline bool Get(const std::string& url) {
return Request(kHttpGet, url, ""); return Request(kHttpGet, url, "");
@ -60,6 +46,24 @@ class RestClient {
return Request(kHttpDelete, url, ""); return Request(kHttpDelete, url, "");
} }
// Response & Result
HttpResponsePtr response() const { return response_; }
int response_status() const {
assert(response_);
return response_->status();
}
const std::string& response_content() const {
assert(response_);
return response_->content();
}
bool timed_out() const { return timed_out_; }
Error error() const { return error_; }
private: private:
bool Request(const std::string& method, const std::string& url, bool Request(const std::string& method, const std::string& url,
std::string&& content); std::string&& content);

@ -0,0 +1,91 @@
#include "webcc/soap_async_client.h"
#include <cassert>
#include <utility> // for move()
#include "webcc/http_async_client.h"
#include "webcc/soap_request.h"
#include "webcc/soap_response.h"
namespace webcc {
SoapAsyncClient::SoapAsyncClient(boost::asio::io_context& io_context,
const std::string& host,
const std::string& port)
: io_context_(io_context),
host_(host), port_(port),
soapenv_ns_(kSoapEnvNamespace),
format_raw_(true), timeout_seconds_(0) {
if (port_.empty()) {
std::size_t i = host_.find_last_of(':');
if (i != std::string::npos) {
port_ = host_.substr(i + 1);
host_ = host_.substr(0, i);
}
}
}
void SoapAsyncClient::Request(const std::string& operation,
std::vector<SoapParameter>&& parameters,
SoapResponseHandler soap_response_handler) {
assert(service_ns_.IsValid());
assert(!url_.empty() && !host_.empty());
assert(!result_name_.empty());
SoapRequest soap_request;
soap_request.set_soapenv_ns(soapenv_ns_);
soap_request.set_service_ns(service_ns_);
soap_request.set_operation(operation);
for (SoapParameter& p : parameters) {
soap_request.AddParameter(std::move(p));
}
std::string http_content;
soap_request.ToXml(format_raw_, indent_str_, &http_content);
HttpRequestPtr http_request;
http_request->set_method(kHttpPost);
http_request->set_url(url_);
http_request->SetContent(std::move(http_content), true);
http_request->SetContentType(kTextXmlUtf8);
http_request->SetHost(host_, port_);
http_request->SetHeader(kSoapAction, operation);
http_request->UpdateStartLine();
HttpAsyncClientPtr http_client(new HttpAsyncClient(io_context_));
if (timeout_seconds_ > 0) {
http_client->set_timeout_seconds(timeout_seconds_);
}
auto http_response_handler = std::bind(&SoapAsyncClient::ResponseHandler,
this, soap_response_handler,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3);
http_client->Request(http_request, http_response_handler);
}
void SoapAsyncClient::ResponseHandler(SoapResponseHandler soap_response_handler,
HttpResponsePtr http_response,
Error error, bool timed_out) {
if (error != kNoError) {
soap_response_handler("", error, timed_out);
} else {
SoapResponse soap_response;
soap_response.set_result_name(result_name_);
if (!soap_response.FromXml(http_response->content())) {
soap_response_handler("", kXmlError, false);
} else {
soap_response_handler(soap_response.result_moved(), kNoError, false);
}
}
}
} // namespace webcc

@ -0,0 +1,85 @@
#ifndef WEBCC_SOAP_ASYNC_CLIENT_H_
#define WEBCC_SOAP_ASYNC_CLIENT_H_
#include <functional>
#include <string>
#include <vector>
#include "webcc/http_async_client.h"
#include "webcc/soap_message.h"
#include "webcc/soap_parameter.h"
namespace webcc {
// Response handler/callback.
typedef std::function<void(std::string, Error, bool)> SoapResponseHandler;
class SoapAsyncClient {
public:
// If |port| is empty, |host| will be checked to see if it contains port or
// not (separated by ':').
SoapAsyncClient(boost::asio::io_context& io_context, // NOLINT
const std::string& host, const std::string& port = "");
~SoapAsyncClient() = default;
DELETE_COPY_AND_ASSIGN(SoapAsyncClient);
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_indent_str(const std::string& indent_str) {
indent_str_ = indent_str;
}
void Request(const std::string& operation,
std::vector<SoapParameter>&& parameters,
SoapResponseHandler soap_response_handler);
private:
void ResponseHandler(SoapResponseHandler soap_response_handler,
HttpResponsePtr http_response,
Error error, bool timed_out);
boost::asio::io_context& io_context_;
std::string host_;
std::string port_; // Leave this empty to use default 80.
// Request URL.
std::string url_;
SoapNamespace soapenv_ns_; // SOAP envelope namespace.
SoapNamespace service_ns_; // Namespace for your web service.
// Response result XML node name.
// E.g., "Result".
std::string result_name_;
// Format request XML without any indentation or line breaks.
bool format_raw_;
// Indent string for request XML.
// Applicable when |format_raw_| is false.
std::string indent_str_;
// Timeout in seconds; only effective when > 0.
int timeout_seconds_;
};
} // namespace webcc
#endif // WEBCC_SOAP_ASYNC_CLIENT_H_

@ -4,8 +4,6 @@
#include <utility> // for move() #include <utility> // for move()
#include "webcc/http_client.h" #include "webcc/http_client.h"
#include "webcc/http_request.h"
#include "webcc/http_response.h"
#include "webcc/soap_request.h" #include "webcc/soap_request.h"
#include "webcc/soap_response.h" #include "webcc/soap_response.h"

@ -39,14 +39,14 @@ class SoapClient {
indent_str_ = indent_str; indent_str_ = indent_str;
} }
bool timed_out() const { return timed_out_; }
Error error() const { return error_; }
bool Request(const std::string& operation, bool Request(const std::string& operation,
std::vector<SoapParameter>&& parameters, std::vector<SoapParameter>&& parameters,
std::string* result); std::string* result);
bool timed_out() const { return timed_out_; }
Error error() const { return error_; }
private: private:
std::string host_; std::string host_;
std::string port_; // Leave this empty to use default 80. std::string port_; // Leave this empty to use default 80.

Loading…
Cancel
Save