I'm sending the following post with FireFox rest client:
POST /WSPublic.asmx HTTP/1.1
Content-Type: application/soap+xml; charset=utf-8
Content-Length: 462
Host: host
Connection: close
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"><soap12:Body><ContadoresTR xmlns="https://xxxxx"><Usuario>user</Usuario><Contrasena>password</Contrasena><NInstalacion>inst</NInstalacion><VersionFicheroEsperado>1</VersionFicheroEsperado></ContadoresTR></soap12:Body></soap12:Envelope>
It works, and I receive the response from the server.
Looking in Wireshark conversations, I see that firstly the RESTClient sends the following stream:
...........fe....0..S.... ..L0g....!...z.P. _....N.im3....8.q.'...6.9.....p>. .+./.
...........3.2.9./.5.
.......c........
ges.leako.com......
.................#..3t.....!...h2-14.spdy/3.1.spdy/3.http/1.1.........
Then I try to do the same using node.js. The HTTP client sends the same post and I don't receive response from the server. Looking at the Wireshark conversations, I see that the first HTTP Client stream the format is different from the RESTClient of firefox.
POST /WSPublic.asmx HTTP/1.1
Content-Type: application/soap+xml; charset=utf-8
Content-Length: 462
Host: host
Connection: close
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"><soap12:Body><ContadoresTR xmlns="https://xxxxxx"><Usuario>user</Usuario><Contrasena>password</Contrasena><NInstalacion>inst</NInstalacion><VersionFicheroEsperado>1</VersionFicheroEsperado></ContadoresTR></soap12:Body></soap12:Envelope>
Here the node.js script:
var http = require("http")
var body = '<?xml version="1.0" encoding="utf-8"?>'
+'<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
+'xmlns:xsd="http://www.w3.org/2001/XMLSchema"'
+'xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">'
+'<soap12:Body>'
+'<ContadoresTR xmlns="https://ges.leako.com/WSPublic">'
+'<Usuario>xxx</Usuario>'
+'<Contrasena>xxx</Contrasena>'
+'<NInstalacion>xxx</NInstalacion>'
+'<VersionFicheroEsperado>x</VersionFicheroEsperado>'
+'</ContadoresTR>'
+'</soap12:Body>'
+'</soap12:Envelope>';
var postRequest = {
host: "ges.leako.com",
path: "/WSPublic.asmx",
port: 443,
method: "POST",
headers: {
'Content-Type': 'application/soap+xml; charset=utf-8',
'Content-Length': Buffer.byteLength(body),
'Connection': 'keep-alive'
}
};
var buffer = "";
var req = http.request( postRequest, function( res ) {
console.log( res.statusCode );
var buffer = "";
res.on( "data", function( data ) { buffer = buffer + data; } );
res.on( "end", function( data ) { console.log( buffer ); } );
});
req.write( body );
req.end();
What I'm doing wrong? Why Firefox send the POST format different than the node.js HTTP Client, and which is that format?
Thanks in advance.
Apart from the 'keep-alive' 'Connection' header and the 'Content-type' one, everything seems fine as mentioned by #mithunsatheesh in this other question how to post XML data in node.js http.request but I guess you were already aware of that since the code is pretty similar in both cases :)
Related
I am attempting to send a POST request to a server I have no control over. The server receives the POST but then sends a response every time an external event happens.
So by "subscribing" with one POST I should be able to receive multiple responses until the connection is dropped.
I have attempted to do this using sockets, but it seems the socket sends as TCP which the server does not recognise - it needs to be HTTP (I checked this using Wireshark as they have an APITool with which to test the connection).
This is my code to receive the data:
var net = require("net");
var client = new net.Socket();
client.connect(
8080,
"hostname.com",
function() {
console.log("Connected");
client.write(`POST /Subscribe HTTP/1.1
Authorization: Basic authcode
Host: hostname.com:8080
Content-Length: 1078
Connection: keep-alive
Keep-Alive: 300
<?xml version="1.0" encoding="UTF-8"?>
<config version="1.7">
... (some XML here)
</config>
`);
console.log("Finished Write");
}
);
client.on("data", function(data) {
console.log("Received " + data.length + " bytes\n" + data);
});
client.on("close", function() {
console.log("Connection closed");
});
client.on("error", function(err) {
console.log("Connection error" + err);
});
client.on("end", function(err) {
console.log("Connection end" + err);
});
Is there a way to force the socket to send as HTTP, or is there a way to receive a "stream" from a POST request over http?
Thank you.
EDIT 1: Adding the raw HTTP code whePOST /SetSubscribe HTTP/1.1
Host: hostname.com:8080
Keep-Alive: 300
Authorization: Basic authkey
Content-Type: application/xml
Content-Length: 1076
<?xml version="1.0" encoding="UTF-8"?>
... XML
</config>
And this gives the response:
<?xml version="1.0" encoding="UTF-8" ?>
<config version="1.7" xmlns="http://www.ipc.com/ver10">
... XML
</config>
With the following headers:
Content-Type: application-xml
Content-Length: 397
Connection: keep-alive
When I watch this in WireShark I see multiple responses coming back but I don't know how to "grab" them in code to use them. Postman doesn't show each of these new responses coming back though.
I want to make the following http request
POST /v1/images HTTP/1.1
Host: api.medium.com
Authorization: Bearer 181d415f34379af07b2c11d144dfbe35d
Content-Type: multipart/form-data; boundary=FormBoundaryXYZ
Accept: application/json
Accept-Charset: utf-8
--FormBoundaryXYZ
Content-Disposition: form-data; name="image"; filename="filename.png"
Content-Type: image/png
IMAGE_DATA
--FormBoundaryXYZ--
It is Medium API
I have attempted following.
var axios = require("axios")
var data = (await axios("https://example.com/image.png")).data;
axios.post("https://api.medium.com/v1/images",{image: data},{
headers: {
"Content-Type" : "multipart/form-data",
"Authorization" : "Bearer " + process.env.key
}
}).then(x=>console.log(x.data))
And I get following error.
Error: Request failed with status code 400
It uses Medium API to upload image, I want to fetch a remote image, and convert it into multipart/form-data and upload it via API, the HTTP request seems confusing, I want the equivalent axios code, someone please help?
Try using FormData instead of plain object?
Example should be like this
const formData = new FormData();
formData.append('image', data);
axios.post('https://api.medium.com/v1/images', formData, {
headers: {
"Content-Type" : "multipart/form-data",
"Authorization" : "Bearer " + process.env.key
}
});
Reference: How to post a file from a form with Axios
I'm attempting to get a SOAP response from a web service without using any libraries in Node, but I'm getting nowhere with the code I have. The WSDL for the service can be found here. I've tested the request in SoapUI, and with curl in a batch file. The JavaScript:
const http = require('http')
const fs = require('fs')
const xml = fs.readFileSync('latlonzipcode.xml','utf-8')
const options = {
hostname : 'graphical.weather.gov',
path : '/xml/SOAP_server/ndfdXMLserver.php',
method : 'POST',
headers : {
'Content-Type' : 'text/xml;charset=utf-8',
'soapAction' : 'https://graphical.weather.gov/xml/DWMLgen/wsdl/ndfdXML.wsdl#LatLonListZipCode'
}
}
var obj = http.request(options,(resp)=>{
let data = ''
console.log(resp.statusCode)
console.log(resp.headers)
resp.on('data',(chunk)=>{
data += chunk
})
resp.on('end',()=>{
console.log(data)
})
}).on('error',(err)=>{
console.log("Error: " + err.message)
})
obj.write(xml)
obj.end()
The SOAP envelope/XML file:
<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:ndf="https://graphical.weather.gov/xml/DWMLgen/wsdl/ndfdXML.wsdl">
<soapenv:Header/>
<soapenv:Body>
<ndf:LatLonListZipCode soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<zipCodeList xsi:type="xsd:string">90210</zipCodeList>
</ndf:LatLonListZipCode>
</soapenv:Body>
</soapenv:Envelope>
and the .bat file - for testing:
:: curl options: -H is for Header --data allows file parameters
curl -H "soapAction: \"https://graphical.weather.gov/xml/DWMLgen/wsdl/ndfdXML.wsdl#LatLonListCityNames\"" -H "Content-Type: text/xml;charset=UTF-8" --data #latlonzipcode.xml https://graphical.weather.gov/xml/SOAP_server/ndfdXMLserver.php > response.xml
The response I receive from the service:
403
{ server: 'AkamaiGHost',
'mime-version': '1.0',
'content-type': 'text/html',
'content-length': '320',
expires: 'Wed, 18 Jul 2018 14:18:05 GMT',
date: 'Wed, 18 Jul 2018 14:18:05 GMT',
connection: 'close' }
<HTML><HEAD>
<TITLE>Access Denied</TITLE>
</HEAD><BODY>
<H1>Access Denied</H1>
You don't have permission to access "http://graphical.weather.gov/xml/SOAP_server/ndfdXMLserver.php" on this server.<P>
Reference #18.7fd23017.1531923485.f45e7526
</BODY>
</HTML>
The batch file works perfectly. Any help would be great. Thanks.
UPDATE
After Googling around I found this. So I added the header User-Agent : headerTest to my options... And finally got a response, unfortunately it was
the WSDL.
As stated in my update above, my original problem was due to not using https and that the web service was blocking requests without a User-Agent header. As for the WSDL file being returned as the response, I mistakenly used GET in my options and forgot to correct it. Finally I suspected that something was going on with writing the XML to the body and found that there was an issue - I found that answer here. Here is the corrected code:
const https = require('https')
const fs = require('fs')
const xml = fs.readFileSync('latlonzipcode.xml','utf-8')
const options = {
hostname : 'graphical.weather.gov',
port : 443,
path : '/xml/SOAP_server/ndfdXMLserver.php',
method : 'POST',
headers : {
'User-Agent' : 'sampleTest',
'Content-Type' : 'text/xml;charset=utf-8',
'soapAction' : 'https://graphical.weather.gov/xml/DWMLgen/wsdl/ndfdXML.wsdl#LatLonListZipCode'
}
}
var obj = https.request(options,(resp)=>{
let data = ''
fs.writeFile('server.log',resp.statusCode+"\n"+JSON.stringify(resp.headers),(err)=>{
err ? console.log(err) : console.log('log file written')
})
resp.on('data',(chunk)=>{
data += chunk
})
resp.on('end',()=>{
fs.writeFile('soap-response.xml',data,(err)=>{
err ? console.log(err) : console.log('data file written')
})
console.log(data)
})
}).on('error',(err)=>{
console.log("Error: " + err.message)
})
/**
* '.write()' is not being used:
* obj.write(xml) ? console.log('op success') : console.log('error!')
* obj.end()
*/
obj.end(xml) ? console.log('op success') : console.log('error!')
Node.js has finally got me excited about JavaScript. Thanks.
I'm trying to use the request.jslibrary to upload a file to box.com using request.post.
I consistently get a return code of 400 and a null body in the response. Not sure how to get at the actual error that box is seeing. The err argument to the callback is null, so there is a response from box.com, but with a statuscode of 400 and a null body.
FYI, the upload succeeds using curl, so the auth token etc. is fine.
I pointed the function below to http://echo.200please.com', and it seems the HTTP POST request I'm sending out is fine.
How do I get to see what error is being seen by box?
request = require"request");
UploadFile = function(filename, callback) {
var formData = {
attributes: JSON.stringify( {
name: filename,
parent: { id: '' + 2764913765 }
}),
file: fs.createReadStream('./temp.bin')
}
var options = {
url: 'https://upload.box.com/api/2.0/files.content',
headers: { Authorization: 'Bearer ' + tokens.access_token},
formData: formData
}
request.post(options,
function(err, response, body) {
if (err) {
console.log('Error Uploading the file');
} else {
console.log('returned:' + body + JSON.stringify(response.headers))
}
});
If I change the URL to point to echo.200please.com, the response I get from echo.200please.com is below, which seems to be the correct format for a file upload request.
> POST / HTTP/1.0
Host: echo.200please.com
Connection: close
Content-Length: 1951
Authorization: Bearer bVPDzG8PgIVRNoqb5LOzD61h6NXhJ6h0
content-type: multipart/form-data; boundary=--------------------------799592280904953105406767
----------------------------799592280904953105406767
Content-Disposition: form-data; name="attributes"
{"name":"testchunkname.1","parent":{"id":"2764913765"}}
----------------------------799592280904953105406767
Content-Disposition: form-data; name="file"; filename="temp.bin"
Content-Type: application/octet-stream
<... file data ...>
OK ... I found the bug :-)
It's a typo in the url
in my program it got set to api/2.0/files.content whereas the correct path in the url should be api/2.0/files/content
i´m trying to get websites / xml objects from the huawei umts stick internal web gui.
I´ve written a wrapper in c using libcurl which works fine. Now i want to port this to node using request.
When i call a url with curl from console like this:
curl -G "http://192.168.1.1/api/monitoring/status"
I get normal result:
<?xml version="1.0" encoding="UTF-8"?>
<response>
<ConnectionStatus>901</ConnectionStatus>
<SignalStrength>99</SignalStrength>
<SignalIcon>5</SignalIcon>
<CurrentNetworkType>4</CurrentNetworkType>
<CurrentServiceDomain>3</CurrentServiceDomain>
<RoamingStatus>0</RoamingStatus>
<BatteryStatus></BatteryStatus>
<BatteryLevel></BatteryLevel>
<simlockStatus></simlockStatus>
</response>
When i try to call this site with request:
var request = require("request");
var options = {
url: "http://192.168.1.1/api/monitoring/status"
};
request.get(options, function(error, response, body) {
if(error)
{
console.log(error);
}
console.log("statusCode: " + response.statusCode);
console.log("statusText: " + response.statusText);
console.log(body);
});
I got an 400 Error:
statusCode: 400
statusText: undefined
<HTML><HEAD>
<TITLE>IPWEBS - 400 Bad Request</TITLE>
</HEAD>
<BODY><H2>400 Bad Request</H2>
<P>The request generated an error response.</P>
</BODY>
</HTML>
Any idea on this subject?
It could be that curl is sending a header that the server requires. Try changing your options to:
var options = {
url: "http://192.168.1.1/api/monitoring/status",
headers: {
'User-Agent': 'curl/7.30.0',
'Accept': '*/*'
}
}