I am trying to build a shipment tracking tool using the Estes Shipment Tracking Web Services which use SOAP. I talked with their web support, and they are able to create a working request using SOAPUI that receives a valid response using my credentials. It would appear that my problem is the inability to replicate the request/response in SOAPUI with node.js. Why am I not able to replicate the SOAPUI request/response in node.js?
The following is the working raw request from SOAPUI that Estes web support used:
POST https://api.estes-express.com:443/ws/estesrtshipmenttracking.base.ws.provider.soapws:EstesShipmentTracking/estesrtshipmenttracking_base_ws_provider_soapws_EstesShipmentTracking_Port HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8
SOAPAction: "estesrtshipmenttracking_base_ws_provider_soapws_EstesShipmentTracking_Binder_shipmentTracking"
Content-Length: 468
Host: api.estes-express.com:443
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
Authorization: Basic XXXXX
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="https://api.estes-express.com/ws/tools/shipment/tracking/v1.1/">
<soapenv:Header/>
<soapenv:Body>
<v1:shipmentTracking>
<search>
<requestID>testroger</requestID>
<!--Optional:-->
<pro>XXXXXX</pro>
</search>
<debug>N</debug>
</v1:shipmentTracking>
</soapenv:Body>
</soapenv:Envelope>
I've omitted the base 64 encoded Basic Auth information above, but I assure you I am using the exact same value in my request.
My request is below, using node.js. I should note that I am providing proxy information in my request, but I have verified that it works in other request functions.
function estes(obj) {
var auth = 'Basic XXXXXXX'
var url = 'https://api.estes-express.com:443/ws/estesrtshipmenttracking.base.ws.provider.soapws:EstesShipmentTracking/estesrtshipmenttracking_base_ws_provider_soapws_EstesShipmentTracking_Port'
const request = require('request')
const fs = require('fs');
const xml = fs.readFileSync('estessample.xml', 'utf-8');
request.post({
uri: url,
headers: {
'SOAPAction': 'estesrtshipmenttracking_base_ws_provider_soapws_EstesShipmentTracking_Binder_shipmentTracking',
'Content-Type': 'text/xml;charset=UTF-8',
'Content-Length': xml.length,
'Host': 'api.estes-express.com:443',
'Authorization': auth
},
proxy: 'XXXXXX',
body: xml
}, function (error, response, body) {
console.log(body)
fs.writeFile("response.txt", body, (err) => {
if (err) console.log(err);
console.log("Successfully Written to File.");
});
})
}
This is the XML that I am posting to their service (estessample.xml), which is the same as what the Estes web services team was using that worked above:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="https://api.estes-express.com/ws/tools/shipment/tracking/v1.1/">
<soapenv:Header/>
<soapenv:Body>
<v1:shipmentTracking>
<search>
<requestID>testroger</requestID>
<!--Optional:-->
<pro>XXXXXXX</pro>
</search>
<debug>N</debug>
</v1:shipmentTracking>
</soapenv:Body>
</soapenv:Envelope>
And lastly, here is the error I am receiving in response.xml:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<soapenv:Fault>
<faultcode>soapenv:Client</faultcode>
<faultstring>[ISS.0088.9164] Access to WSDescriptor estesrtshipmenttracking.base.ws.provider.soapws:EstesShipmentTracking denied.</faultstring>
<faultactor>http://api.estes-express.com/tools</faultactor>
<detail>
<webM:exception xmlns:webM="http://www.webMethods.com/2001/10/soap/encoding">
<webM:className>com.wm.app.b2b.server.AccessException</webM:className>
<webM:message xml:lang="">[ISS.0088.9164] Access to WSDescriptor estesrtshipmenttracking.base.ws.provider.soapws:EstesShipmentTracking denied.</webM:message>
</webM:exception>
</detail>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>
The error is due to an authentication error. I just tried accessing the endpoint and received a similar error.
I believe you are using this node module https://github.com/request/request
After going through the code you have shared I think it might be due the way you have formed the POST request. I would suggest going through the request
module documentation more thoroughly.
request.post({
uri: url,
headers: {
'SOAPAction': 'estesrtshipmenttracking_base_ws_provider_soapws_EstesShipmentTracking_Binder_shipmentTracking',
'Content-Type': 'text/xml;charset=UTF-8'
},
'auth': {
'user': '<username>',
'pass': '<password>',
},
body: xml,
}, function (error, response, body) {
// Code Omitted
})
A simplified sample shown above.
Take note of the auth section. The module will also take care of setting the content-length
header.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With