Search code examples
c++soaphttp-headersgsoap

gSOAP - SOAP-Action Header not set


I have couple of WSDL files and used gSOAP to create C++ Code.

To generate the Code the following commands were used:

\path\to\wsdl2h -I \path\to\import\dir -j -N Service1Prefix -n Namespace1Prefix -o \path\to\output\header\dir\header1.h -q CPPNamespace1 -t \path\to\typemap.dat .\path\to\wsdl1.wsdl

And so on for the remaining WSDL Files. In the gsoap documentation I read that an empty env.h file would be needed that will handle serialization and Error Handling. So I created an empty file for that.

After this I generated the C++ Code for each of the WSDL file with the soap2cpp tool:

\path\to\soap2cpp -1 -C -L -a -A -b -d \path\to\output\dir -i -j -I \path\to\import\dir -n -r -w -x \path\to\header\dir\header1.h

And the env.h

\path\to\soap2cpp -1 -C -L -b -d \path\to\output\dir -j -I \path\to\import\dir -penv  -r -w -x \path\to\env.h

Everything worked and I got the C++ Code.

I put it into my Code and tried a method but prompted with an error.

Error: WSWS3147E: Error: no SOAPAction header!

I tried some fiddling with the parameters of wsdl2h and soap2cpp but did not come to a satisfying result. When I drop the parameter for the prefixs the SOAPAction Header was set but I will get problems when the response contains some objects with the same name but different content.

Some searching did not bring up a working solution for me. Do someone of you might faced this problem before and could offer some help?


Solution

  • It might be the case that the WSDL does not define the SOAP Action header in the wsdl:binding/wsdl:operation/soap:operation/@soapAction attribute, though that is not very likely. However, if this is the case or if the soapAction is not correctly specified in the WSDL, and you know what the SOAP Action header should be, then you can simply set the SOAP Action header manually when invoking the service as follows:

    // create a service proxy object
    SomeProxy proxy;
    // invoke the service at an endpoint URL and SOAP Action, pass parameters:
    if (proxy.someMethod("endpoint URL", "soap action", ...) == SOAP_OK)
      ... // got the results!
    

    This sets the SOAP Action HTTP header to the string provided as the second parameter. You can use NULL for the endpoint and/or the action strings to let the invocation use the WSDL-defined endpoint and action instead.

    PS #1. use only soapcpp2 option -j (preferred) or -i, but do not use both.

    PS #2. why not run wsdl2h on all WSDLs combined? This saves substantial amount of generated code in the end. The service proxy classes are separately generated for the services in the WSDLs anyway with soapcpp2 when services are combined in one big .h file. This way you are also sure that SOAP Headers and SOAP Faults are working out of the box. Explanation: env.h should define all SOAP Headers and SOAP Fault detail structures extracted from the separately generated .h files, which can be tedious to do by hand.