Use HttpClient as member variable inside RestClient and SoapClient.

master
Chunting Gu 7 years ago
parent d2e2935f9d
commit 921defc0e3

@ -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,7 +34,7 @@ void HttpAsyncClient::Request(std::shared_ptr<HttpRequest> request,
request_ = request;
response_handler_ = response_handler;
resolver_->async_resolve(tcp::v4(), request->host(), request->port(kHttpPort),
resolver_.async_resolve(tcp::v4(), request->host(), request->port(kHttpPort),
std::bind(&HttpAsyncClient::ResolveHandler,
shared_from_this(),
std::placeholders::_1,
@ -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;

@ -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);

@ -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;
}

@ -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

@ -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;
}

@ -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());

@ -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) {

Loading…
Cancel
Save