# SOAP Server Tutorial Suppose you want to provide a calculator web service just like the one from [ParaSoft](http://ws1.parasoft.com/glue/calculator.wsdl). Firstly, create a class `CalcService` which is derived from `webcc::SoapService`, override the `Handle` method: ```cpp // calc_service.h #include "webcc/soap_service.h" class CalcService : public webcc::SoapService { public: bool Handle(const webcc::SoapRequest& soap_request, webcc::SoapResponse* soap_response) override; }; ``` The `Handle` method has two parameters, one for request (input), one for response (output). The implementation is quite straightforward: - Get operation (e.g., add) from request; - Get parameters (e.g., x and y) from request; - Calculate the result. - Set namespaces, result name and so on to response. - Set result to response. ```cpp // calc_service.cpp #include "calc_service.h" #include "boost/lexical_cast.hpp" #include "webcc/soap_request.h" #include "webcc/soap_response.h" bool CalcService::Handle(const webcc::SoapRequest& soap_request, webcc::SoapResponse* soap_response) { try { if (soap_request.operation() == "add") { double x = boost::lexical_cast(soap_request.GetParameter("x")); double y = boost::lexical_cast(soap_request.GetParameter("y")); double result = x + y; soap_response->set_soapenv_ns(webcc::kSoapEnvNamespace); soap_response->set_service_ns({ "cal", "http://www.example.com/calculator/" }); soap_response->set_operation(soap_request.operation()); soap_response->set_result_name("Result"); soap_response->set_result(std::to_string(result)); return true; } // Other operations ... } catch (boost::bad_lexical_cast&) { // ... } return false; } ``` Next step, create a `SoapServer` and register `CalcService` to it with a URL. ```cpp int main(int argc, char* argv[]) { // Check argc and argv ... unsigned short port = std::atoi(argv[1]); // Number of worker threads. std::size_t workers = 2; try { webcc::SoapServer server(port, workers); server.RegisterService(std::make_shared(), "/calculator"); server.Run(); } catch (std::exception& e) { std::cerr << "Exception: " << e.what() << std::endl; return 1; } return 0; } ``` The server is created with a **port number** which will be listened on to **asynchnously** accept client connections. The connections will be firstly put into a **queue** and then processed by the **worker threads**. The number of worker threads is determined by the `workers` parameter. When register service, the URL is what the clients will put in the HTTP request to access your service: ``` POST /calculator HTTP/1.1 ``` Registering multiple services to a server is allowed, but the URL must be unique for each service. To invoke the `add` operation of the calculator service, an example of the client HTTP request would be: ``` POST /calculator HTTP/1.1 Content-Type: text/xml; charset=utf-8 Content-Length: 263 Host: localhost:8080 SOAPAction: add 1.000000 2.000000 ``` And the HTTP response is: ``` HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 262 3.000000 ``` See [example/soap_calc_server](https://github.com/sprinfall/webcc/tree/master/example/soap_calc_server) for the full example.