Support to use SOAP 1.1 or 1.2.

master
Chunting Gu 7 years ago
parent ef252c9f74
commit f5fe4e67f7

@ -21,8 +21,8 @@
},
{
"directory": "/home/adam/github/webcc/build/webcc",
"command": "/usr/bin/c++ -DBOOST_ASIO_NO_DEPRECATED -DWEBCC_ENABLE_LOG -DWEBCC_ENABLE_SOAP -DWEBCC_LOG_LEVEL=0 -I/usr/local/include -I/home/adam/github/webcc -I/home/adam/github/webcc/third_party/src -std=c++11 -o CMakeFiles/webcc.dir/http_connection.cc.o -c /home/adam/github/webcc/webcc/http_connection.cc",
"file": "/home/adam/github/webcc/webcc/http_connection.cc"
"command": "/usr/bin/c++ -DBOOST_ASIO_NO_DEPRECATED -DWEBCC_ENABLE_LOG -DWEBCC_ENABLE_SOAP -DWEBCC_LOG_LEVEL=0 -I/usr/local/include -I/home/adam/github/webcc -I/home/adam/github/webcc/third_party/src -std=c++11 -o CMakeFiles/webcc.dir/http_session.cc.o -c /home/adam/github/webcc/webcc/http_session.cc",
"file": "/home/adam/github/webcc/webcc/http_session.cc"
},
{
"directory": "/home/adam/github/webcc/build/webcc",

@ -21,7 +21,6 @@ bool BookService::Handle(const webcc::SoapRequest& soap_request,
webcc::SoapResponse* soap_response) {
const std::string& operation = soap_request.operation();
soap_response->set_soapenv_ns(webcc::kSoapEnvNamespace);
soap_response->set_service_ns({
"ser",
"http://www.example.com/book/"

@ -7,8 +7,9 @@
class CalcClient {
public:
// NOTE: Parasoft's calculator service uses SOAP V1.1.
CalcClient(const std::string& host, const std::string& port)
: soap_client_(host, port) {
: soap_client_(host, port, webcc::kSoapV11) {
soap_client_.SetTimeout(5);
soap_client_.set_url("/glue/calculator");

@ -52,7 +52,6 @@ bool CalcService::Handle(const webcc::SoapRequest& soap_request,
double result = calc(x, y);
soap_response->set_soapenv_ns(webcc::kSoapEnvNamespace);
soap_response->set_service_ns({
"cal",
"http://www.example.com/calculator/"

@ -12,10 +12,11 @@ namespace webcc {
SoapAsyncClient::SoapAsyncClient(boost::asio::io_context& io_context,
const std::string& host,
const std::string& port)
const std::string& port,
SoapVersion soap_version)
: io_context_(io_context),
host_(host), port_(port),
soapenv_ns_(kSoapEnvNamespace),
soap_version_(soap_version),
format_raw_(true), timeout_seconds_(0) {
if (port_.empty()) {
std::size_t i = host_.find_last_of(':');
@ -35,7 +36,13 @@ void SoapAsyncClient::Request(const std::string& operation,
SoapRequest soap_request;
soap_request.set_soapenv_ns(soapenv_ns_);
// Set SOAP envelope namespace according to SOAP version.
if (soap_version_ == kSoapV11) {
soap_request.set_soapenv_ns(kSoapEnvNamespaceV11);
} else {
soap_request.set_soapenv_ns(kSoapEnvNamespaceV12);
}
soap_request.set_service_ns(service_ns_);
soap_request.set_operation(operation);
@ -52,7 +59,13 @@ void SoapAsyncClient::Request(const std::string& operation,
http_request->set_method(kHttpPost);
http_request->set_url(url_);
http_request->SetContent(std::move(http_content), true);
http_request->SetContentType(kTextXmlUtf8);
if (soap_version_ == kSoapV11) {
http_request->SetContentType(kTextXmlUtf8);
} else {
http_request->SetContentType(kAppSoapXmlUtf8);
}
http_request->SetHost(host_, port_);
http_request->SetHeader(kSoapAction, operation);
http_request->UpdateStartLine();

@ -19,7 +19,8 @@ class SoapAsyncClient {
// 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 = "");
const std::string& host, const std::string& port = "",
SoapVersion soap_version = kSoapV12);
~SoapAsyncClient() = default;
@ -59,11 +60,13 @@ class SoapAsyncClient {
std::string host_;
std::string port_; // Leave this empty to use default 80.
SoapVersion soap_version_;
// Request URL.
std::string url_;
SoapNamespace soapenv_ns_; // SOAP envelope namespace.
SoapNamespace service_ns_; // Namespace for your web service.
// Namespace for your web service.
SoapNamespace service_ns_;
// Response result XML node name.
// E.g., "Result".

@ -8,9 +8,10 @@
namespace webcc {
SoapClient::SoapClient(const std::string& host, const std::string& port)
SoapClient::SoapClient(const std::string& host, const std::string& port,
SoapVersion soap_version)
: host_(host), port_(port),
soapenv_ns_(kSoapEnvNamespace),
soap_version_(soap_version),
format_raw_(true), error_(kNoError) {
if (port_.empty()) {
std::size_t i = host_.find_last_of(':');
@ -32,7 +33,13 @@ bool SoapClient::Request(const std::string& operation,
SoapRequest soap_request;
soap_request.set_soapenv_ns(soapenv_ns_);
// Set SOAP envelope namespace according to SOAP version.
if (soap_version_ == kSoapV11) {
soap_request.set_soapenv_ns(kSoapEnvNamespaceV11);
} else {
soap_request.set_soapenv_ns(kSoapEnvNamespaceV12);
}
soap_request.set_service_ns(service_ns_);
soap_request.set_operation(operation);
@ -49,7 +56,13 @@ bool SoapClient::Request(const std::string& operation,
http_request.set_method(kHttpPost);
http_request.set_url(url_);
http_request.SetContent(std::move(http_content), true);
http_request.SetContentType(kTextXmlUtf8);
if (soap_version_ == kSoapV11) {
http_request.SetContentType(kTextXmlUtf8);
} else {
http_request.SetContentType(kAppSoapXmlUtf8);
}
http_request.SetHost(host_, port_);
http_request.SetHeader(kSoapAction, operation);
http_request.UpdateStartLine();

@ -14,7 +14,8 @@ 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& host, const std::string& port = "",
SoapVersion soap_version = kSoapV12);
~SoapClient() = default;
@ -56,11 +57,13 @@ class SoapClient {
std::string host_;
std::string port_; // Leave this empty to use default 80.
SoapVersion soap_version_;
// Request URL.
std::string url_;
SoapNamespace soapenv_ns_; // SOAP envelope namespace.
SoapNamespace service_ns_; // Namespace for your web service.
// Namespace for your web service.
SoapNamespace service_ns_;
// Response result XML node name.
// E.g., "Result".

@ -9,10 +9,25 @@ const std::string kSoapAction = "SOAPAction";
// But in practice, many web servers cannot understand it.
// See: https://www.w3.org/TR/2007/REC-soap12-part0-20070427/#L26854
const std::string kTextXmlUtf8 = "text/xml; charset=utf-8";
const std::string kAppSoapXmlUtf8 = "application/soap+xml; charset=utf-8";
const SoapNamespace kSoapEnvNamespace{
// NOTE:
// According to HTTP 1.1 RFC7231, the following examples are all equivalent,
// but the first is preferred for consistency:
// text/html;charset=utf-8
// text/html;charset=UTF-8
// Text/HTML;Charset="utf-8"
// text/html; charset="utf-8"
// See: https://tools.ietf.org/html/rfc7231#section-3.1.1.1
const SoapNamespace kSoapEnvNamespaceV11{
"soap",
"http://schemas.xmlsoap.org/soap/envelope/"
};
const SoapNamespace kSoapEnvNamespaceV12{
"soap",
"http://www.w3.org/2003/05/soap-envelope"
};
} // namespace webcc

@ -11,11 +11,17 @@ namespace webcc {
extern const std::string kSoapAction;
extern const std::string kTextXmlUtf8;
extern const std::string kAppSoapXmlUtf8;
// -----------------------------------------------------------------------------
enum SoapVersion {
kSoapV11,
kSoapV12,
};
// XML namespace name/url pair.
// E.g., { "soap", "http://schemas.xmlsoap.org/soap/envelope/" }
// E.g., { "soap", "http://www.w3.org/2003/05/soap-envelope" }
struct SoapNamespace {
std::string name;
std::string url;
@ -25,8 +31,9 @@ struct SoapNamespace {
}
};
// CSoap's default namespace for SOAP Envelope.
extern const SoapNamespace kSoapEnvNamespace;
// Default namespaces for SOAP Envelope.
extern const SoapNamespace kSoapEnvNamespaceV11;
extern const SoapNamespace kSoapEnvNamespaceV12;
} // namespace webcc

@ -30,6 +30,15 @@ void SoapRequestHandler::HandleSession(HttpSessionPtr session) {
}
SoapResponse soap_response;
// Set SOAP envelope namespace according to SOAP version.
// NOTE: This could be overwritten by service->Handle() anyway.
if (soap_version_ == kSoapV11) {
soap_response.set_soapenv_ns(kSoapEnvNamespaceV11);
} else {
soap_response.set_soapenv_ns(kSoapEnvNamespaceV12);
}
if (!service->Handle(soap_request, &soap_response)) {
session->SendResponse(HttpStatus::kBadRequest);
return;
@ -37,7 +46,13 @@ void SoapRequestHandler::HandleSession(HttpSessionPtr session) {
std::string content;
soap_response.ToXml(format_raw_, indent_str_, &content);
session->SetResponseContent(std::move(content), kTextXmlUtf8);
if (soap_version_ == kSoapV11) {
session->SetResponseContent(std::move(content), kTextXmlUtf8);
} else {
session->SetResponseContent(std::move(content), kAppSoapXmlUtf8);
}
session->SendResponse(HttpStatus::kOK);
}

@ -5,12 +5,16 @@
#include <string>
#include "webcc/http_request_handler.h"
#include "webcc/soap_globals.h"
namespace webcc {
class SoapRequestHandler : public HttpRequestHandler {
public:
SoapRequestHandler() : format_raw_(true) {}
explicit SoapRequestHandler(SoapVersion soap_version)
: soap_version_(soap_version),
format_raw_(true) {
}
~SoapRequestHandler() override = default;
@ -30,6 +34,9 @@ class SoapRequestHandler : public HttpRequestHandler {
typedef std::map<std::string, SoapServicePtr> UrlServiceMap;
UrlServiceMap url_service_map_;
// Default to kSoapV12.
SoapVersion soap_version_;
// Format response XML without any indentation or line breaks.
bool format_raw_;

@ -12,8 +12,10 @@ namespace webcc {
class SoapServer : public HttpServer {
public:
SoapServer(std::uint16_t port, std::size_t workers)
: HttpServer(port, workers) {
SoapServer(std::uint16_t port, std::size_t workers,
SoapVersion soap_version = kSoapV12)
: HttpServer(port, workers),
request_handler_(soap_version) {
}
~SoapServer() override = default;

Loading…
Cancel
Save