Reorganize examples; fix soap issues.
This commit is contained in:
+7
-17
@@ -30,6 +30,10 @@ set(HEADERS
|
||||
http_server.h
|
||||
http_socket.h
|
||||
queue.h
|
||||
rest_request_handler.h
|
||||
rest_server.h
|
||||
rest_service.h
|
||||
rest_service_manager.h
|
||||
url.h
|
||||
utility.h
|
||||
version.h
|
||||
@@ -51,27 +55,13 @@ set(SOURCES
|
||||
http_server.cc
|
||||
http_socket.cc
|
||||
logger.cc
|
||||
rest_request_handler.cc
|
||||
rest_service_manager.cc
|
||||
rest_service.cc
|
||||
url.cc
|
||||
utility.cc
|
||||
)
|
||||
|
||||
if(WEBCC_ENABLE_REST)
|
||||
set(REST_HEADERS
|
||||
rest_request_handler.h
|
||||
rest_server.h
|
||||
rest_service.h
|
||||
rest_service_manager.h
|
||||
)
|
||||
set(REST_SOURCES
|
||||
rest_request_handler.cc
|
||||
rest_service_manager.cc
|
||||
rest_service.cc
|
||||
)
|
||||
|
||||
set(HEADERS ${HEADERS} ${REST_HEADERS})
|
||||
set(SOURCES ${SOURCES} ${REST_SOURCES})
|
||||
endif()
|
||||
|
||||
if(WEBCC_ENABLE_SOAP)
|
||||
set(SOAP_HEADERS
|
||||
soap_client.h
|
||||
|
||||
@@ -88,7 +88,6 @@ const char* const kTextXml = "text/xml";
|
||||
|
||||
} // namespace media_types
|
||||
|
||||
// TODO: Rename to encodings?
|
||||
namespace charsets {
|
||||
|
||||
const char* const kUtf8 = "utf-8";
|
||||
|
||||
@@ -103,6 +103,25 @@ HttpResponsePtr HttpClientSession::Post(const std::string& url,
|
||||
.headers(std::move(headers)));
|
||||
}
|
||||
|
||||
HttpResponsePtr HttpClientSession::Put(const std::string& url,
|
||||
std::string&& data, bool json,
|
||||
std::vector<std::string>&& headers,
|
||||
HttpRequestArgs&& args) {
|
||||
return Request(args.method(http::kPut)
|
||||
.url(url)
|
||||
.data(std::move(data))
|
||||
.json(json)
|
||||
.headers(std::move(headers)));
|
||||
}
|
||||
|
||||
HttpResponsePtr HttpClientSession::Delete(const std::string& url,
|
||||
std::vector<std::string>&& headers,
|
||||
HttpRequestArgs&& args) {
|
||||
return Request(args.method(http::kDelete)
|
||||
.url(url)
|
||||
.headers(std::move(headers)));
|
||||
}
|
||||
|
||||
void HttpClientSession::InitHeaders() {
|
||||
headers_.Add(http::headers::kUserAgent, http::UserAgent());
|
||||
|
||||
|
||||
@@ -46,6 +46,14 @@ public:
|
||||
std::vector<std::string>&& headers = {},
|
||||
HttpRequestArgs&& args = HttpRequestArgs());
|
||||
|
||||
HttpResponsePtr Put(const std::string& url, std::string&& data, bool json,
|
||||
std::vector<std::string>&& headers = {},
|
||||
HttpRequestArgs&& args = HttpRequestArgs());
|
||||
|
||||
HttpResponsePtr Delete(const std::string& url,
|
||||
std::vector<std::string>&& headers = {},
|
||||
HttpRequestArgs&& args = HttpRequestArgs());
|
||||
|
||||
private:
|
||||
void InitHeaders();
|
||||
|
||||
|
||||
@@ -63,6 +63,9 @@ bool HttpResponse::Prepare() {
|
||||
SetHeader("Server", http::UserAgent());
|
||||
SetHeader("Date", GetHttpDateTimestamp());
|
||||
|
||||
// TODO: Support Keep-Alive.
|
||||
SetHeader(http::headers::kConnection, "Close");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,21 +16,15 @@ bool RestRequestHandler::Bind(RestServicePtr service, const std::string& url,
|
||||
void RestRequestHandler::HandleConnection(HttpConnectionPtr connection) {
|
||||
const HttpRequest& http_request = connection->request();
|
||||
|
||||
// TODO
|
||||
const Url& url = http_request.url();
|
||||
|
||||
if (url.path().empty()) {
|
||||
connection->SendResponse(http::Status::kBadRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
RestRequest rest_request{
|
||||
http_request.method(), http_request.content(), url.query()
|
||||
};
|
||||
|
||||
// Get service by URL path.
|
||||
RestServicePtr service =
|
||||
service_manager_.GetService(url.path(), &rest_request.url_sub_matches);
|
||||
std::string path = "/" + url.path();
|
||||
auto service = service_manager_.GetService(path, &rest_request.url_matches);
|
||||
|
||||
if (!service) {
|
||||
LOG_WARN("No service matches the URL path: %s", url.path().c_str());
|
||||
|
||||
@@ -23,13 +23,13 @@ void RestListService::Handle(const RestRequest& request,
|
||||
void RestDetailService::Handle(const RestRequest& request,
|
||||
RestResponse* response) {
|
||||
if (request.method == http::kGet) {
|
||||
Get(request.url_sub_matches, UrlQuery(request.url_query_str), response);
|
||||
Get(request.url_matches, UrlQuery(request.url_query_str), response);
|
||||
} else if (request.method == http::kPut) {
|
||||
Put(request.url_sub_matches, request.content, response);
|
||||
Put(request.url_matches, request.content, response);
|
||||
} else if (request.method == http::kPatch) {
|
||||
Patch(request.url_sub_matches, request.content, response);
|
||||
Patch(request.url_matches, request.content, response);
|
||||
} else if (request.method == http::kDelete) {
|
||||
Delete(request.url_sub_matches, response);
|
||||
Delete(request.url_matches, response);
|
||||
} else {
|
||||
LOG_ERRO("RestDetailService doesn't support '%s' method.",
|
||||
request.method.c_str());
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace webcc {
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Regex sub-matches of the URL.
|
||||
typedef std::vector<std::string> UrlSubMatches;
|
||||
typedef std::vector<std::string> UrlMatches;
|
||||
|
||||
struct RestRequest {
|
||||
// HTTP method (GET, POST, etc.).
|
||||
@@ -34,7 +34,7 @@ struct RestRequest {
|
||||
const std::string& url_query_str;
|
||||
|
||||
// Regex sub-matches of the URL (usually resource ID's).
|
||||
UrlSubMatches url_sub_matches;
|
||||
UrlMatches url_matches;
|
||||
};
|
||||
|
||||
struct RestResponse {
|
||||
@@ -79,22 +79,22 @@ public:
|
||||
void Handle(const RestRequest& request, RestResponse* response) final;
|
||||
|
||||
public:
|
||||
virtual void Get(const UrlSubMatches& url_sub_matches,
|
||||
virtual void Get(const UrlMatches& url_matches,
|
||||
const UrlQuery& query,
|
||||
RestResponse* response) {
|
||||
}
|
||||
|
||||
virtual void Put(const UrlSubMatches& url_sub_matches,
|
||||
virtual void Put(const UrlMatches& url_matches,
|
||||
const std::string& request_content,
|
||||
RestResponse* response) {
|
||||
}
|
||||
|
||||
virtual void Patch(const UrlSubMatches& url_sub_matches,
|
||||
virtual void Patch(const UrlMatches& url_matches,
|
||||
const std::string& request_content,
|
||||
RestResponse* response) {
|
||||
}
|
||||
|
||||
virtual void Delete(const UrlSubMatches& url_sub_matches,
|
||||
virtual void Delete(const UrlMatches& url_matches,
|
||||
RestResponse* response) {
|
||||
}
|
||||
};
|
||||
|
||||
@@ -31,9 +31,9 @@ bool RestServiceManager::AddService(RestServicePtr service,
|
||||
}
|
||||
}
|
||||
|
||||
RestServicePtr RestServiceManager::GetService(
|
||||
const std::string& url, std::vector<std::string>* sub_matches) {
|
||||
assert(sub_matches != nullptr);
|
||||
RestServicePtr RestServiceManager::GetService(const std::string& url,
|
||||
UrlMatches* matches) {
|
||||
assert(matches != nullptr);
|
||||
|
||||
for (ServiceItem& item : service_items_) {
|
||||
if (item.is_regex) {
|
||||
@@ -43,7 +43,7 @@ RestServicePtr RestServiceManager::GetService(
|
||||
// Any sub-matches?
|
||||
// NOTE: Start from 1 because match[0] is the whole string itself.
|
||||
for (size_t i = 1; i < match.size(); ++i) {
|
||||
sub_matches->push_back(match[i].str());
|
||||
matches->push_back(match[i].str());
|
||||
}
|
||||
|
||||
return item.service;
|
||||
|
||||
@@ -24,12 +24,11 @@ public:
|
||||
bool AddService(RestServicePtr service, const std::string& url,
|
||||
bool is_regex);
|
||||
|
||||
// The |sub_matches| is only available when the |url| bound to the
|
||||
// service is a regular expression and has sub-expressions.
|
||||
// The |matches| is only available when the |url| bound to the service is a
|
||||
// regular expression and has sub-expressions.
|
||||
// E.g., the URL bound to the service is "/instances/(\\d+)", now match
|
||||
// "/instances/12345" against it, you will get one sub-match of "12345".
|
||||
RestServicePtr GetService(const std::string& url,
|
||||
std::vector<std::string>* sub_matches);
|
||||
// "/instances/12345" against it, you will get one match of "12345".
|
||||
RestServicePtr GetService(const std::string& url, UrlMatches* matches);
|
||||
|
||||
private:
|
||||
class ServiceItem {
|
||||
|
||||
+5
-20
@@ -10,19 +10,11 @@
|
||||
|
||||
namespace webcc {
|
||||
|
||||
SoapClient::SoapClient(const std::string& host, const std::string& port,
|
||||
SoapVersion soap_version, std::size_t buffer_size)
|
||||
: host_(host), port_(port), soap_version_(soap_version),
|
||||
SoapClient::SoapClient(const std::string& url, SoapVersion soap_version,
|
||||
std::size_t buffer_size)
|
||||
: url_(url), soap_version_(soap_version),
|
||||
http_client_(buffer_size),
|
||||
format_raw_(true), error_(kNoError) {
|
||||
// Try to extract port from host if it's empty.
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SoapClient::Request(const std::string& operation,
|
||||
@@ -30,7 +22,7 @@ bool SoapClient::Request(const std::string& operation,
|
||||
SoapResponse::Parser parser,
|
||||
std::size_t buffer_size) {
|
||||
assert(service_ns_.IsValid());
|
||||
assert(!url_.empty() && !host_.empty());
|
||||
assert(!url_.empty());
|
||||
|
||||
error_ = kNoError;
|
||||
fault_.reset();
|
||||
@@ -55,14 +47,7 @@ bool SoapClient::Request(const std::string& operation,
|
||||
std::string http_content;
|
||||
soap_request.ToXml(format_raw_, indent_str_, &http_content);
|
||||
|
||||
// TODO
|
||||
std::string url = host_;
|
||||
url += url_;
|
||||
if (!port_.empty()) {
|
||||
url += ":" + port_;
|
||||
}
|
||||
|
||||
HttpRequest http_request(http::kPost, url);
|
||||
HttpRequest http_request(http::kPost, url_);
|
||||
|
||||
http_request.SetContent(std::move(http_content), true);
|
||||
|
||||
|
||||
+2
-10
@@ -13,9 +13,7 @@ namespace webcc {
|
||||
|
||||
class SoapClient {
|
||||
public:
|
||||
// If |port| is empty, |host| will be checked to see if it contains port or
|
||||
// not (separated by ':').
|
||||
explicit SoapClient(const std::string& host, const std::string& port = "",
|
||||
explicit SoapClient(const std::string& url,
|
||||
SoapVersion soap_version = kSoapV12,
|
||||
std::size_t buffer_size = 0);
|
||||
|
||||
@@ -28,8 +26,6 @@ public:
|
||||
http_client_.SetTimeout(seconds);
|
||||
}
|
||||
|
||||
void set_url(const std::string& url) { url_ = url; }
|
||||
|
||||
void set_service_ns(const SoapNamespace& service_ns) {
|
||||
service_ns_ = service_ns;
|
||||
}
|
||||
@@ -71,16 +67,12 @@ public:
|
||||
std::shared_ptr<SoapFault> fault() const { return fault_; }
|
||||
|
||||
private:
|
||||
std::string host_;
|
||||
std::string port_; // Leave this empty to use default 80.
|
||||
std::string url_;
|
||||
|
||||
SoapVersion soap_version_;
|
||||
|
||||
HttpClient http_client_;
|
||||
|
||||
// Request URL.
|
||||
std::string url_;
|
||||
|
||||
// Namespace for your web service.
|
||||
SoapNamespace service_ns_;
|
||||
|
||||
|
||||
@@ -16,7 +16,9 @@ bool SoapRequestHandler::Bind(SoapServicePtr service, const std::string& url) {
|
||||
}
|
||||
|
||||
void SoapRequestHandler::HandleConnection(HttpConnectionPtr connection) {
|
||||
SoapServicePtr service = GetServiceByUrl(connection->request().url().path());
|
||||
std::string path = "/" + connection->request().url().path();
|
||||
|
||||
SoapServicePtr service = GetServiceByUrl(path);
|
||||
if (!service) {
|
||||
connection->SendResponse(http::Status::kBadRequest);
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user