From 091f06e3a66477c526029625e86cc4a2056df464 Mon Sep 17 00:00:00 2001 From: Adam Gu Date: Thu, 11 Jan 2018 19:59:23 +0800 Subject: [PATCH] Update README --- README.md | 127 +++++++++++------- .../calculator_client/calculator_client.h | 2 +- 2 files changed, 78 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index f8c72f8..288c143 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,16 @@ # csoap -A lightweight C++ SOAP client library. [中文版介绍](https://segmentfault.com/a/1190000009874151) -## Usage +A lightweight C++ SOAP client & server library based on Boost.Asio. + +NOTE: The server part is currently under development, not stable enough to be used in a real production. + +## Client Usage Firstly, please install SoapUI if you don't have it. We need SoapUI to generate sample requests for each web service operation. The open source version is good enough. -Take the calculator web service provided by ParaSoft as an example. Download the WSDL from http://ws1.parasoft.com/glue/calculator.wsdl, create a SOAP project within SoapUI (remember to check "Create sample requests for all operations?"), you will see the sample request for "add" operation as the following: +Take the calculator web service provided by ParaSoft as an example. Download the WSDL from http://ws1.parasoft.com/glue/calculator.wsdl, create a SOAP project within SoapUI (remember to check "**Create sample requests for all operations?**"), you will see the sample request for "add" operation as the following: ```xml @@ -20,72 +23,96 @@ Take the calculator web service provided by ParaSoft as an example. Download the ``` -In order to call the "add" operation, we have to send a HTTP request with the above SOAP envelope as the content. Let's see how to do this with csoap. - -```cpp -bool Add() { - // Create a SOAP request. - csoap::SoapRequest soap_request("add"); - - // Set the service namespace. - csoap::Namespace service_ns = { "cal", "http://www.parasoft.com/wsdl/calculator/" }; - soap_request.set_service_ns(service_ns); - - // Add parameters for the operation. - soap_request.AddParameter("x", "1.0"); - soap_request.AddParameter("y", "2.0"); - - // Generate the XML string for the SOAP envelope. - std::string http_request_body; - soap_request.ToXmlString(&http_request_body); +In order to call the "add" operation, we have to send a HTTP request with the above SOAP envelope as the content. Let's see how to do this with *csoap*. - // Create a HTTP request. - csoap::HttpRequest http_request(csoap::kHttpV11); +Firstly, create a class `CalculatorClient` which is derived from `csoap::SoapClient`: - // Set the HTTP request headers. - http_request.set_url("/glue/calculator"); - http_request.set_content_length(http_request_body.size()); - http_request.set_host("ws1.parasoft.com", ""); - http_request.set_soap_action("add"); - - // Send the HTTP request and get the HTTP response. - - csoap::HttpResponse http_response; +```cpp +#include +#include "csoap/soap_client.h" - csoap::HttpClient http_client; - csoap::ErrorCode ec = http_client.SendRequest(http_request, - http_request_body, - &http_response); +class CalculatorClient : public csoap::SoapClient { +public: + CalculatorClient() { + Init(); + } +``` - // Error handling. - if (ec != csoap::kNoError) { - std::cerr << csoap::GetErrorMessage(ec) << std::endl; +Initialize the URL, host, port, etc. in `Init()`: +```cpp +private: + void Init() { + url_ = "/glue/calculator"; + host_ = "ws1.parasoft.com"; + port_ = ""; // Default to "80". + service_ns_ = { "cal", "http://www.parasoft.com/wsdl/calculator/" }; + result_name_ = "Result"; + } +``` + +Because four calculator operations (*add*, *subtract*, *multiply* and *divide*) all have two parameters, we create a wrapper for `SoapClient::Call()`, name is as `Calc`: +```cpp +bool Calc(const std::string& operation, + const std::string& x_name, + const std::string& y_name, + double x, + double y, + double* result) { + // Prepare parameters. + csoap::Parameter parameters[] = { + { x_name, x }, + { y_name, y } + }; + + // Make the call. + std::string result_str; + if (!Call(operation, parameters, 2, &result_str)) { return false; } - // Parse the SOAP response. - std::string result; - csoap::SoapResponse soap_response; - if (!soap_response.Parse(http_response.content(), "addResponse", "Result", &result)) { + // Convert the result from string to double. + try { + *result = boost::lexical_cast(result_str); + } catch (boost::bad_lexical_cast&) { return false; } - std::cout << result << std::endl; - return true; } ``` -It's not that complicated. But you can't code like this for each operation. You have to do some encapsulation, make a general function, add a base class, and so on. Check the "demo" folder for the detailed example. +Finally, we implement the four operations simply as the following: +```cpp +bool Add(double x, double y, double* result) { + return Calc("add", "x", "y", x, y, result); +} + +bool Subtract(double x, double y, double* result) { + return Calc("subtract", "x", "y", x, y, result); +} + +bool Multiply(double x, double y, double* result) { + return Calc("multiply", "x", "y", x, y, result); +} + +bool Divide(double x, double y, double* result) { + return Calc("divide", "numerator", "denominator", x, y, result); +} +``` +See? It's not that complicated. Check folder ***demo/calculator_client*** for the full example. + +## Server Usage +TODO ## Limitations -- Only support HTTP 1.1. - Only support `int`, `double`, `bool` and `string` parameters. - Only support UTF-8 encoded content. +- One connection one call. +- Connection is in synchronous (or blocking) mode; timeout (default to 30s) is configurable. ## Dependencies -- The TCP socket client is based on Boost.Asio. -- The XML parsing is based on TinyXml or PugiXml, a macro `CSOAP_USE_TINYXML` controls which one to use. -- Build system is CMake, but it should be easy to integrate into your project. +- Boost.Asio is used for both client and server. +- XML processing is based on PugiXml, which is already included in the source tree. +- Build system is CMake, but it should be quite easy to integrate into your own project. diff --git a/src/demo/calculator_client/calculator_client.h b/src/demo/calculator_client/calculator_client.h index 7828b54..9d0f401 100644 --- a/src/demo/calculator_client/calculator_client.h +++ b/src/demo/calculator_client/calculator_client.h @@ -7,7 +7,7 @@ #include #include "csoap/soap_client.h" -class CalculatorClient : csoap::SoapClient { +class CalculatorClient : public csoap::SoapClient { public: CalculatorClient();