5

I'm having a really rough time POST'ing to a SOAP web service using the fetch API. I worked out my CORS issues using a chrome plugin, but now it seems to be having an issue with the format of what I'm sending. I've tried implementing fixes I see in other questions, especially in Content-Type and whatnot, but I cannot get any different result. It just plain does not like a < in slot 1.

Based on other questions, the actual 'data' that I am sending does look a little different from other SOAP requests... they mention an Envelope, they define an XML version, etc. Mine is the pure XML data I send in a SOAP service tester here locally. So I guess what I don't know is whether that software is adding additional details to the request 'payload' before sending it to the service.

The WSDL is not very helpful, but I might be looking in the wrong spot.

Any advice is highly appreciated.

My Javascript/fetch:

var base64 = require('base-64');

let url = 'http://SCRB4APUSLSA801:9080/apex/services/argobasicservice';
let username = 'abo055';
let password = 'hidden';
let headers = new Headers();

export const N4RecordScan = {

    submit(data) {

        headers.append('Content-Type', 'text/xml');
        headers.append('SOAPAction', 'basicInvoke');
        headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password));

        let dataPrefix = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:arg="http://www.navis.com/services/argobasicservice"><soapenv:Header/><soapenv:Body><arg:basicInvoke><arg:scopeCoordinateIds>APMT/USLAX/LAX/LAX</arg:scopeCoordinateIds><arg:xmlDoc><![CDATA[';
        let dataSuffix = ']]></arg:xmlDoc></arg:basicInvoke></soapenv:Body></soapenv:Envelope>';

        data = dataPrefix + data + dataSuffix;

        console.log('about to send ' + data);

        fetch(url, {
            body: data,
            method: 'POST',
            mode: 'cors',
            headers: headers,
            credentials: 'include'
        })
            .then(response => console.log(response))
            .catch(function(error) {
                console.log(error);
            });
        //.done();

    }
};

This is what I'm sending in data:

<gate><record-scan><gate-id>USLAX</gate-id><stage-id>asd</stage-id><lane-id>asd</lane-id><external-console-id>asd</external-console-id><truck tag-id="asd" license-nbr="asd"/><equipment><container eqid="asd" on-chassis-id="asd" /><chassis eqid="asd"></chassis></equipment></record-scan></gate>

This is the response I'm getting:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<soapenv:Fault>
<faultcode>soapenv:Server.userException</faultcode>
<faultstring>org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog.</faultstring>
<detail>…</detail>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>

And this is the WSDL for the service I'm reaching out to.

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.navis.com/services/argobasicservice" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" name="ArgobasicService" targetNamespace="http://www.navis.com/services/argobasicservice">
<wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">Argo Services</wsdl:documentation>
<wsdl:types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.navis.com/services/argobasicservice">
<xsd:element name="basicInvoke">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="scopeCoordinateIds" type="xsd:string"/>
<xsd:element maxOccurs="1" minOccurs="1" name="xmlDoc" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="basicInvokeResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="basicInvokeResponse" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="invokeRequest">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="scopeCoordinateIds" type="xsd:string"/>
<xsd:element maxOccurs="1" minOccurs="1" name="request" type="xsd:string"/>
<xsd:element maxOccurs="1" minOccurs="1" name="handler" type="xsd:string"/>
<xsd:element maxOccurs="1" minOccurs="1" name="locale" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="invokeResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="basicInvokeResponse" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="basicInvokeRequest">
<wsdl:part element="tns:basicInvoke" name="basicInvoke"/>
</wsdl:message>
<wsdl:message name="basicInvokeResponse">
<wsdl:part element="tns:basicInvokeResponse" name="basicInvokeResponse"/>
</wsdl:message>
<wsdl:message name="invokeRequest">
<wsdl:part element="tns:invokeRequest" name="invokeRequest"/>
</wsdl:message>
<wsdl:message name="invokeResponse">
<wsdl:part element="tns:invokeResponse" name="invokeResponse"/>
</wsdl:message>
<wsdl:portType name="ArgobasicServicePort">
<!--  name of your wrapped method  -->
<wsdl:operation name="basicInvoke">
<wsdl:input message="tns:basicInvokeRequest"/>
<wsdl:output message="tns:basicInvokeResponse"/>
</wsdl:operation>
<wsdl:operation name="invoke">
<wsdl:input message="tns:invokeRequest"/>
<wsdl:output message="tns:invokeResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ArgobasicServiceSoapBinding" type="tns:ArgobasicServicePort">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<!--  name of your wrapped method  -->
<wsdl:operation name="basicInvoke">
<soap:operation soapAction=""/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="invoke">
<soap:operation soapAction=""/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ArgobasicService">
<wsdl:port binding="tns:ArgobasicServiceSoapBinding" name="ArgobasicServicePort">
<soap:address location="http://scrb4apuslsa701:10080/apex/services/argobasicservice"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
( function(){ window.SIG_EXT = {}; } )()
runelynx
  • 403
  • 2
  • 4
  • 17
  • 1
    1. Please fix your code sample. Minimum effort. Did you copy-paste a diff? – Evert Feb 21 '18 at 01:15
  • 1
    2. SOAP is xml, and you're sending JSON-related headsers. 3. You are indeed missing a `` line. – Evert Feb 21 '18 at 01:17
  • @Evert Corrected code and updated to what I have after spending loosely 8 hours at work on this. I ended up using SoapUI to try and see a real submission that works... and that gave me the you show as well as the construction my WSDL is actually seeking. The good news is that the first submission actually works now! But if I click my submit button any more for additional submits, they all fail w/ bad credentials error from the SOAP. If I reload my page, again.. first works, all subsequent fail. Any ideas? – runelynx Feb 21 '18 at 01:34
  • 1
    Glad to see you made it a lot further! I don't have an answer to this new question though :( I wonder if you need to do `let headers = new Headers();` every time (move it into the function body). – Evert Feb 21 '18 at 01:42
  • 1
    small note, unrelated to your problem. Everywhere you currently use `let`, you should use `const`. But yea this has no bearing on the outcome – Evert Feb 21 '18 at 01:43
  • 1
    Ok I'm actually somewhat sure it's the headers, because you keep appending to the same set of headers and set a larger set of headers for every request ;) – Evert Feb 21 '18 at 01:44
  • @Evert That was it. Moved the headers declaration into the function and it now works beautifully. Do you want to post as an answer? – runelynx Feb 21 '18 at 17:44

1 Answers1

2

You're re-using the same Headers object for each request. Which means that you're tacking on new Authorization headers every time you're doing a new request.

Move the let headers = new Headers(); into the function body (and use const), to probably make it work!

Evert
  • 93,428
  • 18
  • 118
  • 189