Support CDATA for SOAP request and response; Rename Parameter to SoapParameter; Add book server and client example for SOAP.

This commit is contained in:
Adam Gu
2018-07-19 11:19:51 +08:00
parent 23d948cebb
commit 223e59cc7a
48 changed files with 1395 additions and 412 deletions
+15
View File
@@ -0,0 +1,15 @@
set(TARGET_NAME soap_book_server)
set(SRCS
../common/book.cc
../common/book.h
../common/book_xml.cc
../common/book_xml.h
book_service.cc
book_service.h
main.cc)
add_executable(${TARGET_NAME} ${SRCS})
target_link_libraries(${TARGET_NAME} webcc pugixml ${Boost_LIBRARIES})
target_link_libraries(${TARGET_NAME} "${CMAKE_THREAD_LIBS_INIT}")
+220
View File
@@ -0,0 +1,220 @@
#include "example/soap_book_server/book_service.h"
#include <iostream>
#include <list>
#include <sstream>
#include "webcc/logger.h"
#include "webcc/soap_request.h"
#include "webcc/soap_response.h"
#include "example/common/book.h"
#include "example/common/book_xml.h"
// -----------------------------------------------------------------------------
static BookStore g_book_store;
// -----------------------------------------------------------------------------
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/"
});
soap_response->set_operation(operation);
soap_response->set_result_name("Result");
if (operation == "CreateBook") {
return CreateBook(soap_request, soap_response);
} else if (operation == "GetBook") {
return GetBook(soap_request, soap_response);
} else if (operation == "ListBooks") {
return ListBooks(soap_request, soap_response);
} else if (operation == "DeleteBook") {
return DeleteBook(soap_request, soap_response);
} else {
LOG_ERRO("Operation '%s' is not supported.", operation.c_str());
return false;
}
return false;
}
bool BookService::CreateBook(const webcc::SoapRequest& soap_request,
webcc::SoapResponse* soap_response) {
// Request SOAP envelope:
// <soap:Envelope xmlns:soap="...">
// <soap:Body>
// <ser:CreateBook xmlns:ser="..." />
// <ser:book>
// <![CDATA[
// <book>
// <title>1984</title>
// <price>12.3</price>
// </book>
// ]]>
// </ser:book>
// </ser:CreateBook>
// </soap:Body>
// </soap:Envelope>
// Response SOAP envelope:
// <soap:Envelope xmlns:soap="...">
// <soap:Body>
// <ser:CreateBookResponse xmlns:ser="...">
// <ser:Result>
// <![CDATA[
// <webcc type = "response">
// <status code = "0" message = "ok">
// <book>
// <id>1</id>
// </book>
// </webcc>
// ]]>
// </ser:Result>
// </ser:CreateBookResponse>
// </soap:Body>
// </soap:Envelope>
const std::string& title = soap_request.GetParameter("title");
const std::string& book_xml = soap_request.GetParameter("book");
Book book;
XmlStringToBook(book_xml, &book); // TODO: Error handling
std::string id = g_book_store.AddBook(book);
std::string response_xml = NewResultXml(0, "ok", "book", "id",
id.c_str());
soap_response->set_result_moved(std::move(response_xml), true);
return true;
}
bool BookService::GetBook(const webcc::SoapRequest& soap_request,
webcc::SoapResponse* soap_response) {
// Request SOAP envelope:
// <soap:Envelope xmlns:soap="...">
// <soap:Body>
// <ser:GetBook xmlns:ser="..." />
// <ser:id>1</ser:id>
// </ser:GetBook>
// </soap:Body>
// </soap:Envelope>
// Response SOAP envelope:
// <soap:Envelope xmlns:soap="...">
// <soap:Body>
// <ser:GetBookResponse xmlns:ser="...">
// <ser:Result>
// <![CDATA[
// <webcc type = "response">
// <status code = "0" message = "ok">
// <book>
// <id>1</id>
// <title>1984</title>
// <price>12.3</price>
// </book>
// </webcc>
// ]]>
// </ser:Result>
// </ser:GetBookResponse>
// </soap:Body>
// </soap:Envelope>
const std::string& id = soap_request.GetParameter("id");
const Book& book = g_book_store.GetBook(id);
soap_response->set_result_moved(NewResultXml(0, "ok", book), true);
return true;
}
bool BookService::ListBooks(const webcc::SoapRequest& soap_request,
webcc::SoapResponse* soap_response) {
// Request SOAP envelope:
// <soap:Envelope xmlns:soap="...">
// <soap:Body>
// <ser:ListBooks xmlns:ser="..." />
// </soap:Body>
// </soap:Envelope>
// Response SOAP envelope:
// <soap:Envelope xmlns:soap="...">
// <soap:Body>
// <ser:ListBooksResponse xmlns:ser="...">
// <ser:Result>
// <![CDATA[
// <webcc type = "response">
// <status code = "0" message = "ok">
// <books>
// <book>
// <id>1</id>
// <title>1984</title>
// <price>12.3</price>
// </book>
// ...
// </books>
// </webcc>
// ]]>
// </ser:Result>
// </ser:ListBooksResponse>
// </soap:Body>
// </soap:Envelope>
const std::list<Book>& books = g_book_store.books();
soap_response->set_result_moved(NewResultXml(0, "ok", books), true);
return true;
}
bool BookService::DeleteBook(const webcc::SoapRequest& soap_request,
webcc::SoapResponse* soap_response) {
// Request SOAP envelope:
// <soap:Envelope xmlns:soap="...">
// <soap:Body>
// <ser:DeleteBook xmlns:ser="..." />
// <ser:id>1</ser:id>
// </ser:DeleteBook>
// </soap:Body>
// </soap:Envelope>
// Response SOAP envelope:
// <soap:Envelope xmlns:soap="...">
// <soap:Body>
// <ser:DeleteBookResponse xmlns:ser="...">
// <ser:Result>
// <![CDATA[
// <webcc type = "response">
// <status code = "0" message = "ok">
// </webcc>
// ]]>
// </ser:Result>
// </ser:DeleteBookResponse>
// </soap:Body>
// </soap:Envelope>
const std::string& id = soap_request.GetParameter("id");
if (g_book_store.DeleteBook(id)) {
soap_response->set_result_moved(NewResultXml(0, "ok"), true);
} else {
soap_response->set_result_moved(NewResultXml(1, "error"), true);
}
return true;
}
+25
View File
@@ -0,0 +1,25 @@
#ifndef EXAMPLE_SOAP_BOOK_SERVER_BOOK_SERVICE_H_
#define EXAMPLE_SOAP_BOOK_SERVER_BOOK_SERVICE_H_
#include "webcc/soap_service.h"
class BookService : public webcc::SoapService {
public:
bool Handle(const webcc::SoapRequest& soap_request,
webcc::SoapResponse* soap_response) override;
private:
bool CreateBook(const webcc::SoapRequest& soap_request,
webcc::SoapResponse* soap_response);
bool GetBook(const webcc::SoapRequest& soap_request,
webcc::SoapResponse* soap_response);
bool ListBooks(const webcc::SoapRequest& soap_request,
webcc::SoapResponse* soap_response);
bool DeleteBook(const webcc::SoapRequest& soap_request,
webcc::SoapResponse* soap_response);
};
#endif // EXAMPLE_SOAP_BOOK_SERVER_BOOK_SERVICE_H_
+40
View File
@@ -0,0 +1,40 @@
#include <iostream>
#include "webcc/logger.h"
#include "webcc/soap_server.h"
#include "example/soap_book_server/book_service.h"
void Help(const char* argv0) {
std::cout << "Usage: " << argv0 << " <port>" << std::endl;
std::cout << " E.g.," << std::endl;
std::cout << " " << argv0 << " 8080" << std::endl;
}
int main(int argc, char* argv[]) {
if (argc < 2) {
Help(argv[0]);
return 1;
}
WEBCC_LOG_INIT("", webcc::LOG_CONSOLE);
std::uint16_t port = static_cast<std::uint16_t>(std::atoi(argv[1]));
std::size_t workers = 2;
try {
webcc::SoapServer server(port, workers);
// Customize response XML format.
server.set_format_raw(false);
server.set_indent_str(" ");
server.Bind(std::make_shared<BookService>(), "/book");
server.Run();
} catch (const std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
return 1;
}
return 0;
}