Support to use SOAP 1.1 or 1.2.
This commit is contained in:
@@ -21,8 +21,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"directory": "/home/adam/github/webcc/build/webcc",
|
"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",
|
"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_connection.cc"
|
"file": "/home/adam/github/webcc/webcc/http_session.cc"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"directory": "/home/adam/github/webcc/build/webcc",
|
"directory": "/home/adam/github/webcc/build/webcc",
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ bool BookService::Handle(const webcc::SoapRequest& soap_request,
|
|||||||
webcc::SoapResponse* soap_response) {
|
webcc::SoapResponse* soap_response) {
|
||||||
const std::string& operation = soap_request.operation();
|
const std::string& operation = soap_request.operation();
|
||||||
|
|
||||||
soap_response->set_soapenv_ns(webcc::kSoapEnvNamespace);
|
|
||||||
soap_response->set_service_ns({
|
soap_response->set_service_ns({
|
||||||
"ser",
|
"ser",
|
||||||
"http://www.example.com/book/"
|
"http://www.example.com/book/"
|
||||||
|
|||||||
@@ -7,8 +7,9 @@
|
|||||||
|
|
||||||
class CalcClient {
|
class CalcClient {
|
||||||
public:
|
public:
|
||||||
|
// NOTE: Parasoft's calculator service uses SOAP V1.1.
|
||||||
CalcClient(const std::string& host, const std::string& port)
|
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_.SetTimeout(5);
|
||||||
|
|
||||||
soap_client_.set_url("/glue/calculator");
|
soap_client_.set_url("/glue/calculator");
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ bool CalcService::Handle(const webcc::SoapRequest& soap_request,
|
|||||||
|
|
||||||
double result = calc(x, y);
|
double result = calc(x, y);
|
||||||
|
|
||||||
soap_response->set_soapenv_ns(webcc::kSoapEnvNamespace);
|
|
||||||
soap_response->set_service_ns({
|
soap_response->set_service_ns({
|
||||||
"cal",
|
"cal",
|
||||||
"http://www.example.com/calculator/"
|
"http://www.example.com/calculator/"
|
||||||
|
|||||||
@@ -12,10 +12,11 @@ namespace webcc {
|
|||||||
|
|
||||||
SoapAsyncClient::SoapAsyncClient(boost::asio::io_context& io_context,
|
SoapAsyncClient::SoapAsyncClient(boost::asio::io_context& io_context,
|
||||||
const std::string& host,
|
const std::string& host,
|
||||||
const std::string& port)
|
const std::string& port,
|
||||||
|
SoapVersion soap_version)
|
||||||
: io_context_(io_context),
|
: io_context_(io_context),
|
||||||
host_(host), port_(port),
|
host_(host), port_(port),
|
||||||
soapenv_ns_(kSoapEnvNamespace),
|
soap_version_(soap_version),
|
||||||
format_raw_(true), timeout_seconds_(0) {
|
format_raw_(true), timeout_seconds_(0) {
|
||||||
if (port_.empty()) {
|
if (port_.empty()) {
|
||||||
std::size_t i = host_.find_last_of(':');
|
std::size_t i = host_.find_last_of(':');
|
||||||
@@ -35,7 +36,13 @@ void SoapAsyncClient::Request(const std::string& operation,
|
|||||||
|
|
||||||
SoapRequest soap_request;
|
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_service_ns(service_ns_);
|
||||||
|
|
||||||
soap_request.set_operation(operation);
|
soap_request.set_operation(operation);
|
||||||
@@ -52,7 +59,13 @@ void SoapAsyncClient::Request(const std::string& operation,
|
|||||||
http_request->set_method(kHttpPost);
|
http_request->set_method(kHttpPost);
|
||||||
http_request->set_url(url_);
|
http_request->set_url(url_);
|
||||||
http_request->SetContent(std::move(http_content), true);
|
http_request->SetContent(std::move(http_content), true);
|
||||||
|
|
||||||
|
if (soap_version_ == kSoapV11) {
|
||||||
http_request->SetContentType(kTextXmlUtf8);
|
http_request->SetContentType(kTextXmlUtf8);
|
||||||
|
} else {
|
||||||
|
http_request->SetContentType(kAppSoapXmlUtf8);
|
||||||
|
}
|
||||||
|
|
||||||
http_request->SetHost(host_, port_);
|
http_request->SetHost(host_, port_);
|
||||||
http_request->SetHeader(kSoapAction, operation);
|
http_request->SetHeader(kSoapAction, operation);
|
||||||
http_request->UpdateStartLine();
|
http_request->UpdateStartLine();
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ class SoapAsyncClient {
|
|||||||
// If |port| is empty, |host| will be checked to see if it contains port or
|
// If |port| is empty, |host| will be checked to see if it contains port or
|
||||||
// not (separated by ':').
|
// not (separated by ':').
|
||||||
SoapAsyncClient(boost::asio::io_context& io_context, // NOLINT
|
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;
|
~SoapAsyncClient() = default;
|
||||||
|
|
||||||
@@ -59,11 +60,13 @@ class SoapAsyncClient {
|
|||||||
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.
|
||||||
|
|
||||||
|
SoapVersion soap_version_;
|
||||||
|
|
||||||
// Request URL.
|
// Request URL.
|
||||||
std::string url_;
|
std::string url_;
|
||||||
|
|
||||||
SoapNamespace soapenv_ns_; // SOAP envelope namespace.
|
// Namespace for your web service.
|
||||||
SoapNamespace service_ns_; // Namespace for your web service.
|
SoapNamespace service_ns_;
|
||||||
|
|
||||||
// Response result XML node name.
|
// Response result XML node name.
|
||||||
// E.g., "Result".
|
// E.g., "Result".
|
||||||
|
|||||||
+16
-3
@@ -8,9 +8,10 @@
|
|||||||
|
|
||||||
namespace webcc {
|
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),
|
: host_(host), port_(port),
|
||||||
soapenv_ns_(kSoapEnvNamespace),
|
soap_version_(soap_version),
|
||||||
format_raw_(true), error_(kNoError) {
|
format_raw_(true), error_(kNoError) {
|
||||||
if (port_.empty()) {
|
if (port_.empty()) {
|
||||||
std::size_t i = host_.find_last_of(':');
|
std::size_t i = host_.find_last_of(':');
|
||||||
@@ -32,7 +33,13 @@ bool SoapClient::Request(const std::string& operation,
|
|||||||
|
|
||||||
SoapRequest soap_request;
|
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_service_ns(service_ns_);
|
||||||
|
|
||||||
soap_request.set_operation(operation);
|
soap_request.set_operation(operation);
|
||||||
@@ -49,7 +56,13 @@ bool SoapClient::Request(const std::string& operation,
|
|||||||
http_request.set_method(kHttpPost);
|
http_request.set_method(kHttpPost);
|
||||||
http_request.set_url(url_);
|
http_request.set_url(url_);
|
||||||
http_request.SetContent(std::move(http_content), true);
|
http_request.SetContent(std::move(http_content), true);
|
||||||
|
|
||||||
|
if (soap_version_ == kSoapV11) {
|
||||||
http_request.SetContentType(kTextXmlUtf8);
|
http_request.SetContentType(kTextXmlUtf8);
|
||||||
|
} else {
|
||||||
|
http_request.SetContentType(kAppSoapXmlUtf8);
|
||||||
|
}
|
||||||
|
|
||||||
http_request.SetHost(host_, port_);
|
http_request.SetHost(host_, port_);
|
||||||
http_request.SetHeader(kSoapAction, operation);
|
http_request.SetHeader(kSoapAction, operation);
|
||||||
http_request.UpdateStartLine();
|
http_request.UpdateStartLine();
|
||||||
|
|||||||
+6
-3
@@ -14,7 +14,8 @@ class SoapClient {
|
|||||||
public:
|
public:
|
||||||
// If |port| is empty, |host| will be checked to see if it contains port or
|
// If |port| is empty, |host| will be checked to see if it contains port or
|
||||||
// not (separated by ':').
|
// 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;
|
~SoapClient() = default;
|
||||||
|
|
||||||
@@ -56,11 +57,13 @@ class SoapClient {
|
|||||||
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.
|
||||||
|
|
||||||
|
SoapVersion soap_version_;
|
||||||
|
|
||||||
// Request URL.
|
// Request URL.
|
||||||
std::string url_;
|
std::string url_;
|
||||||
|
|
||||||
SoapNamespace soapenv_ns_; // SOAP envelope namespace.
|
// Namespace for your web service.
|
||||||
SoapNamespace service_ns_; // Namespace for your web service.
|
SoapNamespace service_ns_;
|
||||||
|
|
||||||
// Response result XML node name.
|
// Response result XML node name.
|
||||||
// E.g., "Result".
|
// E.g., "Result".
|
||||||
|
|||||||
+16
-1
@@ -9,10 +9,25 @@ const std::string kSoapAction = "SOAPAction";
|
|||||||
// But in practice, many web servers cannot understand it.
|
// But in practice, many web servers cannot understand it.
|
||||||
// See: https://www.w3.org/TR/2007/REC-soap12-part0-20070427/#L26854
|
// See: https://www.w3.org/TR/2007/REC-soap12-part0-20070427/#L26854
|
||||||
const std::string kTextXmlUtf8 = "text/xml; charset=utf-8";
|
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",
|
"soap",
|
||||||
"http://schemas.xmlsoap.org/soap/envelope/"
|
"http://schemas.xmlsoap.org/soap/envelope/"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const SoapNamespace kSoapEnvNamespaceV12{
|
||||||
|
"soap",
|
||||||
|
"http://www.w3.org/2003/05/soap-envelope"
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace webcc
|
} // namespace webcc
|
||||||
|
|||||||
+10
-3
@@ -11,11 +11,17 @@ namespace webcc {
|
|||||||
extern const std::string kSoapAction;
|
extern const std::string kSoapAction;
|
||||||
|
|
||||||
extern const std::string kTextXmlUtf8;
|
extern const std::string kTextXmlUtf8;
|
||||||
|
extern const std::string kAppSoapXmlUtf8;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
enum SoapVersion {
|
||||||
|
kSoapV11,
|
||||||
|
kSoapV12,
|
||||||
|
};
|
||||||
|
|
||||||
// XML namespace name/url pair.
|
// 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 {
|
struct SoapNamespace {
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string url;
|
std::string url;
|
||||||
@@ -25,8 +31,9 @@ struct SoapNamespace {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// CSoap's default namespace for SOAP Envelope.
|
// Default namespaces for SOAP Envelope.
|
||||||
extern const SoapNamespace kSoapEnvNamespace;
|
extern const SoapNamespace kSoapEnvNamespaceV11;
|
||||||
|
extern const SoapNamespace kSoapEnvNamespaceV12;
|
||||||
|
|
||||||
} // namespace webcc
|
} // namespace webcc
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,15 @@ void SoapRequestHandler::HandleSession(HttpSessionPtr session) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SoapResponse soap_response;
|
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)) {
|
if (!service->Handle(soap_request, &soap_response)) {
|
||||||
session->SendResponse(HttpStatus::kBadRequest);
|
session->SendResponse(HttpStatus::kBadRequest);
|
||||||
return;
|
return;
|
||||||
@@ -37,7 +46,13 @@ void SoapRequestHandler::HandleSession(HttpSessionPtr session) {
|
|||||||
|
|
||||||
std::string content;
|
std::string content;
|
||||||
soap_response.ToXml(format_raw_, indent_str_, &content);
|
soap_response.ToXml(format_raw_, indent_str_, &content);
|
||||||
|
|
||||||
|
if (soap_version_ == kSoapV11) {
|
||||||
session->SetResponseContent(std::move(content), kTextXmlUtf8);
|
session->SetResponseContent(std::move(content), kTextXmlUtf8);
|
||||||
|
} else {
|
||||||
|
session->SetResponseContent(std::move(content), kAppSoapXmlUtf8);
|
||||||
|
}
|
||||||
|
|
||||||
session->SendResponse(HttpStatus::kOK);
|
session->SendResponse(HttpStatus::kOK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,16 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "webcc/http_request_handler.h"
|
#include "webcc/http_request_handler.h"
|
||||||
|
#include "webcc/soap_globals.h"
|
||||||
|
|
||||||
namespace webcc {
|
namespace webcc {
|
||||||
|
|
||||||
class SoapRequestHandler : public HttpRequestHandler {
|
class SoapRequestHandler : public HttpRequestHandler {
|
||||||
public:
|
public:
|
||||||
SoapRequestHandler() : format_raw_(true) {}
|
explicit SoapRequestHandler(SoapVersion soap_version)
|
||||||
|
: soap_version_(soap_version),
|
||||||
|
format_raw_(true) {
|
||||||
|
}
|
||||||
|
|
||||||
~SoapRequestHandler() override = default;
|
~SoapRequestHandler() override = default;
|
||||||
|
|
||||||
@@ -30,6 +34,9 @@ class SoapRequestHandler : public HttpRequestHandler {
|
|||||||
typedef std::map<std::string, SoapServicePtr> UrlServiceMap;
|
typedef std::map<std::string, SoapServicePtr> UrlServiceMap;
|
||||||
UrlServiceMap url_service_map_;
|
UrlServiceMap url_service_map_;
|
||||||
|
|
||||||
|
// Default to kSoapV12.
|
||||||
|
SoapVersion soap_version_;
|
||||||
|
|
||||||
// Format response XML without any indentation or line breaks.
|
// Format response XML without any indentation or line breaks.
|
||||||
bool format_raw_;
|
bool format_raw_;
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -12,8 +12,10 @@ namespace webcc {
|
|||||||
|
|
||||||
class SoapServer : public HttpServer {
|
class SoapServer : public HttpServer {
|
||||||
public:
|
public:
|
||||||
SoapServer(std::uint16_t port, std::size_t workers)
|
SoapServer(std::uint16_t port, std::size_t workers,
|
||||||
: HttpServer(port, workers) {
|
SoapVersion soap_version = kSoapV12)
|
||||||
|
: HttpServer(port, workers),
|
||||||
|
request_handler_(soap_version) {
|
||||||
}
|
}
|
||||||
|
|
||||||
~SoapServer() override = default;
|
~SoapServer() override = default;
|
||||||
|
|||||||
Reference in New Issue
Block a user