I am trying to code the following solution in C using gSOAP:

* read some existing XML from a buffer (or file) into a gSOAP DOM tree 
structure (SOAP_DOM_TREE)
* manipulate some of the soap_dom_elements
* and then send it as the body of a SOAP request to web service using gSOAP

For various reasons we want to manipulate the XML generically using the DOM, 
rather than using generated or custom serializers/deserializers.

I can successfully read in the XML file and the DOM structure looks as 
expected, I serialize the tree and send it successfully, but the request is 
rejected by the HTTP layer with error 400 "Bad Request". My sent gSoap messages 
are recorded in a log file, and when examining it, it is clear that the HTTP 
Content-Length is incorrect. The length is specified as 232 but the actual XML 
data is 612 bytes.

My XML input file does not contain any "SOAP-ENV:Envelope" or "SOAP-ENV:Body 
elements", just the payload. 

The resulting HTTP Post is as follows. 232 bytes is reached before the end of 
the Envelope.

     POST /sdk HTTP/1.1
     Host: quahog.corp.bb
     User-Agent: gSOAP/2.7
     Content-Type: text/xml; charset=utf-8
     Content-Length: 232
     Connection: close
     SOAPAction: ""
     
     <?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";>
             <SOAP-ENV:Body>
                     <vim:RetrieveServiceContent xmlns:vim="urn:vim2"  
                                            
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>
                             <vim:_this type="ServiceInstance" 
                                        
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
                                   
xsi:type="vim:ManagedObjectReference">ServiceInstance</vim:_this>
                     </vim:RetrieveServiceContent>
             </SOAP-ENV:Body>
     </SOAP-ENV:Envelope>

Below I have included my source code. The point at which it fails is in the 
following "if" statement 

         if (soap_begin_recv(gpDomSoap)
                        || soap_envelope_begin_in(gpDomSoap)
                        || soap_recv_header(gpDomSoap)
                        || soap_body_begin_in(gpDomSoap))

as indicated by the comment "/* FAILS HERE" where Soap error 400 is being 
returned. The error "HTTP Error: 400 Bad Request" is also echoed to the command 
line.

static struct soap gpDomSoap = soap_new1(SOAP_DOM_TREE | SOAP_C_UTFSTRING);

LIBEXTERN int VmwDomSendRequest
(
        const char *soap_endpoint,
        const char *soap_action,
        char *pstrXmlInputFile
)
{
        int iResult = SOAP_OK;
        struct soap_dom_element dom;
        char *pstrErrorString = NULL;

        gpDomSoap->encodingStyle = NULL;
        soap_begin(gpDomSoap);
        soap_serializeheader(gpDomSoap);

        if (NULL != pstrXmlInputFile)
        {
                FileHandleT tFileHandle;

                if (TRUE == FileSysOpen(&tFileHandle, 
                                                pstrXmlInputFile, 
                                                FILE_MODE_READ_TEXT))
                {
                        gpDomSoap->recvfd = tFileHandle;  // Read XML from a 
file

                        // Read in the XML

                        if (soap_begin_recv(gpDomSoap)
                                        || NULL == 
soap_in_xsd__anyType(gpDomSoap, NULL, &dom, NULL)
                                        || soap_end_recv(gpDomSoap))
                        {
                                iResult = gpSoap->error;
                                TRACE((-1,__LINE__,NORMAL,
                                                        "DOM: Read XML from 
file failed = %d", iResult));
                        }
                        else
                        {
                                struct soap_dom_element *ptrDomElement;
                                struct soap_dom_attribute *ptrDomAttribute;

                                TRACE((-1,__LINE__,NORMAL,"DOM: Read XML into 
tree"));
                                gpDomSoap->recvfd = 0; // Set back to stdin

                                TRACE((-1,__LINE__,NORMAL,"DOM: Connecting to 
'%s' action '%s'",
                                                        
STR_STRING(soap_endpoint),
                                                        
STR_STRING(soap_action)));

                                soap_set_namespaces(gpDomSoap, 
vim_pjg_namespaces);

                                // Connect to server, serialize the DOM and 
send it

                                if (soap_connect(gpDomSoap, soap_endpoint, 
soap_action)
                                                || 
soap_envelope_begin_out(gpDomSoap)
                                                || soap_putheader(gpDomSoap)
                                                || 
soap_body_begin_out(gpDomSoap)
                                                || 
soap_put_xsd__anyType(gpDomSoap, 
                                                                                
&dom, 
                                                                                
"-vim:RetrieveServiceContent", 
                                                                                
NULL)
                                                || soap_body_end_out(gpDomSoap)
                                                || 
soap_envelope_end_out(gpDomSoap)
                                                || soap_end_send(gpDomSoap))
                                {
                                        iResult = gpDomSoap->error;
                                        TRACE((-1,__LINE__,NORMAL,"DOM: Send 
failed = %d", iResult));
                                        soap_closesock(gpDomSoap);
                                }
                                else
                                {
                                        struct soap_dom_element response;
                                        struct soap_dom_element *ptrDomElement;
                                        struct soap_dom_attribute 
*ptrDomAttribute;

                                        TRACE((-1,__LINE__,NORMAL,"DOM: Send 
XML OK"));
                                        
                                        // Read response...

                                        soap_default_xsd__anyType(gpDomSoap, 
&response);
                                        
                                        if (soap_begin_recv(gpDomSoap)
                                                        || 
soap_envelope_begin_in(gpDomSoap)
                                                        || 
soap_recv_header(gpDomSoap)
                                                        || 
soap_body_begin_in(gpDomSoap))
                                        {
                                                /********************/
                                                /*                  */
                                                /* FAILS HERE       */
                                                /* with Error = 400 */
                                                /*                  */
                                                *********************/

                                                iResult = gpDomSoap->error;
                                                TRACE((-1,__LINE__,NORMAL,"DOM: 
Soap recv failed = %d", iResult));
                                                
                                                soap_closesock(gpDomSoap);
                                        }
                                        else
                                        {
                                                
soap_get_xsd__anyType(gpDomSoap, &response, 
                                                                                
                "RetrieveServiceContentResponse", "");
                                                soap_body_end_in(gpDomSoap);
                                                soap_end_recv(gpDomSoap);

                                                soap_closesock(gpDomSoap);

                                                // Parse the returned result
                                                
                                        } 
                                } 
                        } 
                        FileSysClose(&tFileHandle);
                } 
        }
        return iResult;
}


Reply via email to