gSOAP: How to use SOAP instead of POST for specific service/schema - soap

First off, let me apologize, because I don't know much about SOAP and most of what I'm saying is probably nonsense.
I upgraded some client-side code that was generated using gSoap 2.8.4 to gSoap 2.8.93
As far as I can tell, the program only sends one request to the server. Previously this request was wrapped in
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns2="bmf.gv.at:pkt/PKTSoap" xmlns:ns1="bmf.gv.at:pkt" xmlns:ns3="bmf.gv.at:pkt/PKTSoap12">
<SOAP-ENV:Body>
...
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
However with the code generated by the new version this envelope is missing. I understand that this is because the request is generated as a REST request instead of a SOAP one. I've found threads that talk about the //gsoap directive for the service setting the method-protocol to SOAP instead of POST, but I can only find these directives for requests to the sub-services /PKTSoap and /PKTSoap12, not to the root service bmf.gv.at:pkt, to which the request is sent. In fact that is not even called a service in the code, it's called a schema. And the requests to it are called top-level root elements of the schema. They are all automatically generated as REST requests.
My question is how can I instruct gSoap to generate all requests as SOAP1.1 requests? Any help whatsoever is greatly appreciated.
WSDL: https://pastebin.com/bmC8Hx6M
typemap.dat is the default one with the following appended:
ns1 = "bmf.gv.at:pkt"
ns2 = "bmf.gv.at:pkt/PKTSoap"
ns3 = "bmf.gv.at:pkt/PKTSoap12"
And I use the following commands to generate:
wsdl2h.exe -c -g -N ns %1.wsdl
soapcpp2.exe -c -C -I./import -1 %1.h

It is not clear from your question which request messages do not include the envelope.
Here is a quick way to test the generated source code, to verify that the SOAP1.1 envelope and body are included (I've used C++ here):
wsdl2h -L -g -N ns service.wsdl
soapcpp2 -1 -C -I import service.h
A small demo client, to test the request message:
#include "soapH.h"
#include "PKTSoap.nsmap"
int main()
{
struct soap *soap = soap_new1(SOAP_XML_INDENT);
_ns1__DatenpoolkontoErzeugen req;
_ns1__Verarbeitung res;
req.soap_default(soap);
soap_call___ns2__PKTDatenpoolkontoErzeugen(soap, "http://", NULL, &req, res);
}
Compiled with:
c++ -o service service.cpp soapC.cpp soapClient.cpp stdsoap2.cpp
Then run:
$ ./service
POST / HTTP/1.1
Host:
User-Agent: gSOAP/2.8
Content-Type: text/xml; charset=utf-8
Content-Length: 526
Connection: close
SOAPAction: "bmf.gv.at:pkt/PKTDatenpoolkontoErzeugen"
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns2="bmf.gv.at:pkt/PKTSoap" xmlns:ns1="bmf.gv.at:pkt" xmlns:ns3="bmf.gv.at:pkt/PKTSoap12">
<SOAP-ENV:Body>
<ns1:DatenpoolkontoErzeugen>
<ns1:Absender xsi:nil="true"/>
</ns1:DatenpoolkontoErzeugen>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
This shows that bmf.gv.at:pkt requests are sent exactly as specified in the WSDL.

Related

Bloomberg Data License web services access from Powershell

I have a X509 certificate (e.g. C:\Cert\BBcert.pl2) and a password (e.g. "XYZ") with which I should use to authenticate and the DLWS here https://service.bloomberg.com/assets/dl/dlws.wsdl
I can use a SOAP GUI client to connect and do some queries but how do I go about using the certificate, password and link above in powershell so I can send some queries?
If anyone has used the Bloomberg Data License Web Services and can provide a complete example how to fetch some pricing data?
Start with:
curl --cert .\BloombergDLWS.p12:MyP#$$w0rd -H "Content-Type: text/xml;charset=utf-8" -H 'SOAPAction: \"submitGetDataRequest\"' -d "#submitGetDataRequest.xml" --request-target 'https://dlws.bloomberg.com/dlps' --url 'https://dlws.bloomberg.com/dlps'
Three notes about the CURL command:
The request-target flag is necessary. Otherwise it sends POST /dlps HTTP/1.1 instead of POST /dlps HTTP/1.1 and results in a 502 BAD GATEWAY error.
Escape the SOAPAction quotes, otherwise you get Failed to convert request to BAS: Failed to find action index for SOAP action 'submitGetDataRequest' when converting SOAP request for service ID 125322
Read the SOAP envelope XML from a file. Inline XML, besides vastly inflating the command length, generated a ParseError even though I had copied it in carefully as one line.
Where submitGetDataRequest.xml contains
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://services.bloomberg.com/datalicense/dlws/ps/20071001">
<soapenv:Header/>
<soapenv:Body>
<ns:submitGetDataRequest>
<ns:headers>
<ns:secmaster>true</ns:secmaster>
</ns:headers>
<ns:fields>
<ns:field>NAME</ns:field>
<ns:field>TICKER</ns:field>
<ns:field>CPN</ns:field>
<ns:field>MATURITY</ns:field>
<ns:field>ID_BB_GLOBAL</ns:field>
</ns:fields>
<ns:instruments>
<ns:instrument>
<ns:id>912810CY2</ns:id>
<ns:type>CUSIP</ns:type>
</ns:instrument>
</ns:instruments>
</ns:submitGetDataRequest>
</soapenv:Body>
</soapenv:Envelope>
This returns a response that doesn't contain the data you want, but it does include a responseId code to use in a second request.
<?xml version="1.0" encoding="UTF-8" ?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<dlws:submitGetDataResponse xmlns='http://services.bloomberg.com/datalicense/dlws/ps/20071001'
xmlns:dlws="http://services.bloomberg.com/datalicense/dlws/ps/20071001"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<dlws:statusCode>
<dlws:code>0</dlws:code>
<dlws:description>Success</dlws:description>
</dlws:statusCode>
<dlws:requestId>01234567-89AB-CDEF-0123-456789ABCDEF</dlws:requestId>
<dlws:responseId>ABCDEF0123-4567890AB</dlws:responseId>
</dlws:submitGetDataResponse>
</soap:Body>
</soap:Envelope>
You must insert the responseId code into another request like so (saved as retrieveGetDataResponse.xml):
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://services.bloomberg.com/datalicense/dlws/ps/20071001">
<soapenv:Header/>
<soapenv:Body>
<ns:retrieveGetDataRequest>
<ns:responseId>ABCDEF0123-4567890AB</ns:responseId>
</ns:retrieveGetDataRequest>
</soapenv:Body>
</soapenv:Envelope>
Wait a few minutes, then submit the final request, saving your data as DataResponse.xml:
curl --cert .\BloombergDLWS.p12:MyP#$$w0rd -H "Content-Type: text/xml;charset=utf-8" -H 'SOAPAction: \"retrieveGetDataResponse\"' -d "#retrieveGetDataResponse.xml" --request-target 'https://dlws.bloomberg.com/dlps' --url 'https://dlws.bloomberg.com/dlps' -o DataResponse.xml
Submitting this request too soon will return a result that basically says it's not ready, try again later.

CISCO WebDialer API, The AXIS engine could not find a target service to invoke

I'm trying to use Cisco WebDialer API but have a few issues with it:
When I try to send the following SOAP request
<?xml version="1.0" encoding="utf-8" ?>
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:WD70">
<soapenv:Header/>
<soapenv:Body>
<urn:makeCallSoap soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<in0 xsi:type="urn:Credential">
<userID xsi:type="xsd:string">user******</userID>
<password xsi:type="xsd:string">pass*****</password>
</in0>
<in1 xsi:type="soapenc:string" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">1234</in1>
<in2 xsi:type="urn:UserProfile">
<user xsi:type="xsd:string">wd</user>
<deviceName xsi:type="xsd:string">SEP001558C8970F</deviceName>
<lineNumber xsi:type="xsd:string">901234565</lineNumber>
<supportEM xsi:type="xsd:boolean">false</supportEM>
<locale xsi:type="xsd:string">English</locale>
<dontAutoClose xsi:type="xsd:boolean">false</dontAutoClose>
<dontShowCallConf xsi:type="xsd:boolean">true</dontShowCallConf>
</in2>
</urn:makeCallSoap>
</soapenv:Body>
</soapenv:Envelope>
to https://SERVER:PORT/webdialer/services/WebdialerSoapService70 I got the following error:
The AXIS engine could not find a target service to invoke! targetService is WebdialerSoapService70
When I try to access directly https:///webdialer/services/WebdialerSoapService70 via browser I get the following message:
AXIS error
No service is available at this URL
My question is what is wrong? Do I miss something in my request or required service isn't running?
Thank you.
Ok, thanks to my colleague I've got the answer. You need to go to the following link:
https://SERVER:PORT/webdialer/services
And you'll see list of all working services and links to them. In my case right link was:
https://SERVER:PORT/webdialer/services/WebdialerSoapService
After I've changed it everything begin to work. And yes, when you open right link in browser you have to get the following message:
WebdialerSoapService
Hi there, this is an AXIS service!
Perhaps there will be a form for invoking the service here...

wso2 ESB request is truncated

i'm using fresh installation of wso2 esb 4.8.1 with stanalone default configuration.
when i send soap request to my backend (perl service with soap lite), the body of POST request is truncated like this according to tcpdump:
SOAPAction: ""
Content-Type: text/xml
Content-Length: 511
Host: 192.168.11.234:8181
Connection: Keep-Alive
User-Agent: Synapse-PT-HttpComponents-NIO
<?xml version="1.0" encoding="UTF-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="htt
p://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Body>
<deleteAccountForHost xmlns="AbcdeHostingPhysicalHostManagerCPanelService">
<host xsi:type="xsd:string">zs000.abcde.net</host>
<user xsi:type="xsd:string">tstauto</user>
</deleteAccountForHost>
</soap:Body>
</soap:Envel
You can see that closing tag '</soap:Envel' is truncated.
But when i enable SOAP-tracer the request body becomes valid.
i use PT transport. I tried to switch transport to the nhttp and this problem seems to be disappeared.
So the question is: how to configure PT transport to avoid such strange behavior?
UPD1:
it seems that the problem occurs only when set the property FORCE_HTTP_1.0 and transport is PT
I got the same problem, but I set DISABLE_CHUNKING.
After many tries I tested that disabling chunking or forcing HTTP 1.0 results in truncated request.
I use WSO2 ESB version 4.8.1, client is SoapUI 5.0.0 or SoapClient from PHP 5.5.11.
When I use "Try this service" in ESB, then request is not truncated.
After switching from HTTP PassThrough Transport to HTTP-NIO Transport service behind endpoint receives complete request, but then I can't download WSDL of tenant.

BancBox SOAP API getClient - call fails using WCF client infrastructure

I apologize in advance if this post feels too long. But 1) this is my first post ever and 2) I have really been over the river and through the woods trying to figure this out.
The Add Service Reference feature in Visual Studio 2012 produces a proxy that (apparently) generates invalid SOAP messages. I suspect it has to do with serialization or how the proxy types are decorated but I cannot seem to figure it out. Help is much appreciated.
Detail 1. My environment is Visual Studio 2012 and I have created a .NET 4.5 class library with a service reference to https://sandbox-api.bancbox.com/v1/BBXPort?wsdl. I'm attempting to call the getClient() function; which is defined here. (http://www.bancbox.com/api/view/45)
The code looks like this:
public void GetClient()
{
// create an instance of the service reference proxy class
var bbx=newBBXClient();
bbx.ChannelFactory.Endpoint.Behaviors.Remove<System.ServiceModel.Description.ClientCredentials>();
bbx.ChannelFactory.Endpoint.Behaviors.Add(new CustomCredentials());
bbx.ClientCredentials.UserName.UserName="MY_USERNAME";
bbx.ClientCredentials.UserName.Password="MY_PASSWORD";
var customerId=newid {
subscriberReferenceId="44XX33YY"
};
var request=newgetClientRequest {
subscriberId=MY_SUBSCRIBER_ID,
clientId=customerId
};
var response=bbx.getClient(request);
}
Detail 2. I have made many successful calls into the web service via SoapUI. The successful SoapUI-produced SOAP messages look like this
<soapenv:Envelope xmlns:sch="schema.bancbox.com" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-11">
<wsse:Username>MY_USERNAME</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">MY_PASSWORD</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">tRLo6AlRKl+/rULiKq6A6g==</wsse:Nonce>
<wsu:Created>2013-02-22T18:32:02.204Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<sch:getClient>
<getClientRequest>
<subscriberId>MY_SUBSCRIBER_ID</subscriberId>
<clientId>
<!--Optional:-->
<subscriberReferenceId>44XX33YY</subscriberReferenceId>
</clientId>
</getClientRequest>
</sch:getClient>
</soapenv:Body>
</soapenv:Envelope>
Detail 3. Per Fiddler, my failed SOAP messages look like this
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPozcAgEH0QhJHloqMBWUf3mAAAAAA5wy3enJkDUGU8IaMUCFyEjzfL+1Uez1HhAvEeFpJ+30ACQAA</VsDebuggerCausalityData>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<o:UsernameToken u:Id="uuid-6e1c9f81-0651-41f7-b659-26b191bf7e13-1" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<o:Username>MY_USERNAME</o:Username>
<o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">MY_PASSWORD</o:Password>
<o:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">hGggJkxurSkHQ3MKoeBK6AmEHNs=</o:Nonce>
<u:Created>2013-02-23T11:24:47.663Z</u:Created>
</o:UsernameToken>
</o:Security>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<getClient xmlns="schema.bancbox.com">
<getClientRequest xmlns="">
<subscriberId>MY_SUBSCRIBER_ID</subscriberId>
<clientId>
<subscriberReferenceId>XX55YY22</subscriberReferenceId>
</clientId>
</getClientRequest>
</getClient>
</s:Body>
</s:Envelope>
The SOAP message above is produced when running the GetClient() method. GetClient throws the following Exception.
System.ServiceModel.FaultException
Unmarshalling Error: cvc-elt.4.2: Cannot resolve 'getClientRequest' to a type definition for element 'getClientRequest'.
When I replay the same failing message using SoapUI, I get the following response:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>soap:Client</faultcode>
<faultstring>Unmarshalling Error: cvc-elt.4.2: Cannot resolve 'getClientRequest' to a type definition for element 'getClientRequest'. </faultstring>
</soap:Fault>
</soap:Body>
</soap:Envelope>
Detail 4. Based on my research, this indicates that the server on the other end is Apache CXS. It's choking on my SOAP request. So I started playing around with my SOAP message and submitting it via SoapUI.
The first glaring distance in the successful message and my fail message are these lines
SUCCESS
<sch:getClient>
<getClientRequest>
FAIL
<getClient xmlns="schema.bancbox.com">
<getClientRequest xmlns="">
So the first thing that I did was make my getClientRequest tag identical to the successful one.
<getClient xmlns="schema.bancbox.com">
<getClientRequest>
This produced the following response.
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>Found element {schema.bancbox.com}getClientRequest but could not find matching RPC/Literal part</faultstring>
</soap:Fault>
</soap:Body>
</soap:Envelope>
The next thing that I did is change the way the getClient tag is assigned a schema.
BEFORE
<getClient xmlns="schema.bancbox.com">
AFTER
<s:Envelope xmlns:bb="schema.bancbox.com" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
. . .
<bb:getClient>
<getClientRequest>
. . .
</bb:getClient>
The resultant SOAP message looks like this and it is successful.
<s:Envelope xmlns:bb="schema.bancbox.com" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPozcAgEH0QhJHloqMBWUf3mAAAAAA5wy3enJkDUGU8IaMUCFyEjzfL+1Uez1HhAvEeFpJ+30ACQAA</VsDebuggerCausalityData>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<o:UsernameToken u:Id="uuid-6e1c9f81-0651-41f7-b659-26b191bf7e13-1" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<o:Username>MY_USERNAME</o:Username>
<o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">MY_PASSWORD</o:Password>
<o:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">hGggJkxurSkHQ3MKoeBK6AmEHNs=</o:Nonce>
<u:Created>2013-02-23T11:24:47.663Z</u:Created>
</o:UsernameToken>
</o:Security>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<bb:getClient>
<getClientRequest>
<subscriberId>MY_SUBSCRIBER_ID</subscriberId>
<clientId>
<subscriberReferenceId>XX55YY22</subscriberReferenceId>
</clientId>
</getClientRequest>
</bb:getClient>
</s:Body>
</s:Envelope>
So the million dollar questions are WHY and HOW.
*WHY does the .NET proxy class serialize the SOAP message the way it does?
*HOW do I fix it? How can I may my proxy serialize into the SOAP message above? How can I force the serializer to define shorthand for the message namespace in the Envelop and then use the shorthand in the message tag?
FYI, to even get to this point I had to get past a number of WCF WSE issues and ended up implementing the solution so generously provided on Rich Stahls blog. I would post the link but apparently I don't have enough rep.
From I understand, the SOAP message that WCF produces is syntactically correct. However, Java CXF web services are very rigid with regards to the SOAP messages that they will accept.
The solution to specific problem setting aliases for xml namespace definitions in the Operation node of the SOAP messages produced by WCF proxies involves implementing a Custom Message Inspector is detailed here: Force WCF to create an xml namespace alias in client proxy.
This has completely resolved my issue.

ServiceStack: Incorrect metadata for SOAP?

I followed the Create your first webservice tutorial. When I go to the Hello Service Soap11 metadata page, I see the following:
POST /xml/reply/Hello HTTP/1.1
Host: localhost
Content-Type: application/xml
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ...
</soap:Envelope>
The line POST /xml/reply/Hello HTTP/1.1 seems incorrect. When I use the Postman Rest Client and post to /xml/reply/hello to test the SOAP endpoint. It doesn't work. The response is a 400 Bad Request with a message "Could not deserialize 'application/xml' request..."
Then I change the URL to make the request post to /soap11 instead, it works with status code 200 OK.
This problem happens for the Soap12 metadata page too.
Seems like something is not right with the metadata page generation?
By looking at the code, this does look like a bug.
I have fixed the problem and submitted a pull request to ServiceStack, pending for acceptance.
Pull request: https://github.com/ServiceStack/ServiceStack/pull/389
Update: Pull request has been merged into ServiceStack master branch. Problem solved!