Trouble understanding how to craft a SOAP request - node.js

I have to download something from a webservice via SOAP interface. The documentation for the interface is rather sparse so I have trouble understanding how to request from it.
This is the .wsdl specification.
This is the .xsd one.
The idea is:
Logging in to get session key (I did this successfully)
Using the session key to request available data (where I am having problems)
Using this key to request specific data
Logging out again
I am successfully getting the session key and using it with the request for the databox. Unfortunately, I'm only ever getting HTTP 404 as a response and I don't know how to find the problem since 404 also shows up when the session key is wrong ("asdfg" for example).
This is the XML I am sending:
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<getDatabox xmlns="https://finanzonline.bmf.gv.at/fon/ws/databox">
<tid>${tid}</tid>
<benid>${benid}</benid>
<id>${sessionToken}</id>
<erltyp>${erltyp}</erltyp>
<ts_zust_von>20-08-2017</ts_zust_von>
<ts_zust_bis>25-08-2017</ts_zust_bis>
</getDatabox>
</soap:Body>
</soap:Envelope>
This is the method I am using (I removed some ugliness from it, like the xmlDatabox which is initialized in the method for example):
function getDataBox(sessionToken, erltyp) {
return new Promise((resolve, reject) => {
var body = [];
var https = require("https");
var req = https.request(optionsDatabox, res => {
res.setEncoding("utf8");
res.on("data", chunk => {
console.log("daty");
console.log(chunk);
body.push(chunk);
});
res.on("end", () => {
console.log("STATUSCODE: " + res.statusCode);
resolve(body.join(""));
});
res.on("error", err => {
reject(err);
});
});
req.write(xmlDatabox);
req.end();
});
}
Now everything is sent as it should be sent. Also, the method and xml are (except for the important stuff) the same for getDatabox() and loginRequest() (which works). The only response is HTTPS 404.
How do I find what is wrong?
How do I prevent this frustration next time? (e.g. by knowing immediately what methods should be used)
EDIT: I'm not using the soap module because I had no success with it.

Okay..
I used SoapUI to find out how the request should look like, since I didn't know much about the .wsld and .xsd formats.
SoapUI reads those two files and creates the appropriate xml for it, which you just have to fill out. It also shows you the URL to which you have to send your request, which I didn't know at first either.

Related

How to modify a response in Electron

Let's say that I'm using a GET request on https://example.com and the response is this:
This is a response message.
How would I modify it in a way so that in my code, so that it can change the response to say something like this:
This is a MODIFIED response message.
For example, if my Electron app were to navigate to https://example.com, the screen would show me the modified content instead of the original content.
Essentially, I am trying to literally modify the request.
I have based my code off of this question but it only shows a proof of concept with a pre-typed Buffer, as in my situation I'd like modify the response instead of outright replacing it. So, my code looks like this:
protocol.interceptBufferProtocol("http", (req, CALLBACK) => {
if(req.url.includes("special url here")) {
var request = net.request({
method: req.method,
headers: req.headers,
url: req.url
});
request.on("response", (rp) => {
var d = [];
rp.on("data", c => d.push(c));
rp.on("end", () => {
var e = Buffer.concat(d);
console.log(e.toString());
// do SOMETHING with 'e', the response, then callback it.
CALLBACK(e);
});
});
request.end();
} else {
// Is supposedly going to carry out the request without interception
protocol.uninterceptProtocol("http");
}
}
This is supposed to manually request the URL, grab the response and return it. Without the protocol event, it works and gives me a response, but after some debugging, this piece of code consistently calls the same URL over and over with no response.
There is also the WebRequest API, but there is no way of modifying the response body, you can only modify the request headers & related content.
I haven't looked fully into Chromium-based solutions, but after looking at this, I'm not sure if it is possible to modify the response so it appears on my app's end in the first place. Additionally, I'm not familiar with the Chromium/Puppeteer messages that get sent all over the place.
Is there an elegant way to have Electron to get a URL response/request, call the URL using the headers/body/etc., then save & modify the response to appear different in Electron?

NodeJS http.request fails when header is too large

My code is as follows
var http = require('http');
var host=...
var postData=({
//some fun stuff
})
var postOptions ={
host: host,
path: '/api/dostuff',
method: 'POST',
headers:{
AppID:"some stuff",
Authorization: "OAuth token",
"Content-Type":"application/json"
},
};
var req = http.request(postOptions, function(res){
var data = '';
res.on('data', function (chunk) {
data += chunk;
});
res.on('end', function () {
//sanitize data stuff here
console.log("DATA HERE: "+ data);
return data;
});
});
req.write(JSON.stringify(postData));
req.end();
It's a basic HTTP post to a C# server. The important stuff is in the headers. I send the app ID (which is ~50 characters) and the OAuth token (which can be thousands of characters). Right now, the server isn't set up to do anything with the Authorization header. It doesn't even check if its there.
My problem is that when I populate the Authorization header (or any header) with a few random characters as a test, the post succeeds. When I tried it again with a full valid Authorization token (which, to reiterate, is very long) it fails. No matter which part of the header i fill, once it gets too full it returns an error. The error I receive is "Processing of the HTTP request resulted in an exception. Please see the HTTP response returned by the 'Response' property of this exception for details". I was somewhat certain this is a server issue, but when I tried running the exact same body and headers in Postman, I got a valid response.
Does anyone have any idea what is causing this?
There's a compiled constant that's defined to be 80k for Node HTTP headers. Are you running into that? I'd recommend seeing how big the header is with your OAuth token. It shouldn't exceed 80k though, and FWIW, even a kilobyte is huge for OAuth... But regardless... Try dumping the size of the headers (in bytes).

Connecting to a web service using SOAP

I am currently working on a node based application trying to make a request to a SOAP based service. I am making use of the node-soap module to work through this.
https://github.com/vpulim/node-soap
Currently i have the following implementation
var soap = require('soap');
var url = 'http:/xxxx/xxxx/xxxx?WSDL';
var appKey = 'ABYRCEE';
var xml = {
appKey: appKey,
mac: 'xxxxxxxx'
}
soap.createClient(url, function(err, client){
//console.log('Client:', client);
client.getAllDocsisVideoInfo(xml, function(err, result){
if(err){
console.log(err);
}
});
});
For the service to respond, i have a sample request in xml format, as the following
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:doc="http://xxx.xxx.com">
<soapenv:Header/>
<soapenv:Body>
<doc:getAllDocsisVideoInfo>
<appKey>"appKey"</appKey>
<mac>xxxxxxx</mac>
</doc:getAllDocsisVideoInfo>
</soapenv:Body>
</soapenv:Envelope>
As you can see from the above that i have to pass in appKey and mac values and upon a successful request this will send back successful response in xml format with the appropriate response.
I am able to see client object return back with the appropriate functions, but upon calling the client.getAllDocsisVideoInfo(....), i seem to see the following error
S:Client: Cannot find dispatch method for {}getAllDocsisVideoInfo
I am not sure of the why? Is it because of the way i am passing in the xml object, how do i pass in the sample request?
Looking at the node-soap api:
https://www.npmjs.com/package/soap
It looks like you have to call the function in the following manner:
client.getAllDocsisVideoInfo(xml, function(err, result, raw, soapHeader){
})
If you want to call it like you had it in your code, then I think you need to use the following:
Copy and paste from the API...
client.MyService.MyPort.MyFunction({name: 'value'}, function(err, result) {
// result is a javascript object
})
So after spending hours on this and banging my head, i was able to get a successful response by overriding the namespace prefix, by removing the namespace prefix.
For example, the following object needed to be passed as
var xml = {
':appKey': appKey,
':mac': 'xxxxxxxx'
}
Instead
var xml = {
appKey: appKey,
mac: 'xxxxxxxx'
}
This piece of the node-soap documentation [https://github.com/vpulim/node-soap#overriding-the-namespace-prefix][1] helped in figuring out the issue.

Node.js - Stream Binary Data Straight from Request to Remote server

I've been trying to stream binary data (PDF, images, other resources) directly from a request to a remote server but have had no luck so far. To be clear, I don't want to write the document to any filesystem. The client (browser) will make a request to my node process which will subsequently make a GET request to a remote server and directly stream that data back to the client.
var request = require('request');
app.get('/message/:id', function(req, res) {
// db call for specific id, etc.
var options = {
url: 'https://example.com/document.pdf',
encoding: null
};
// First try - unsuccessful
request(options).pipe(res);
// Second try - unsuccessful
request(options, function (err, response, body) {
var binaryData = body.toString('binary');
res.header('content-type', 'application/pdf');
res.send(binaryData);
});
});
Putting both data and binaryData in a console.log show that the proper data is there but the subsequent PDF that is downloaded is corrupt. I can't figure out why.
Wow, never mind. Found out Postman (Chrome App) was hijacking the request and response somehow. The // First Try example in my code excerpt works properly in browser.

Node.js SOAP Call with Complex Types

I am currently attempting to use node-soap (https://github.com/milewise/node-soap) to make calls to Authorize.net's SOAP server. However, I cannot seem to get my client code pass the proper parameters. I know that the function is calling the server since I get a server error response.
When I examine the WSDL, I notice that the server call requires ComplexType parameters. Is there a way to create the ComplexTypes that I need or can I just use Javascript objects? Here is my current code:
var soap = require('soap');
var url = 'https://api.authorize.net/soap/v1/Service.asmx?WSDL';
soap.createClient(url, function(err, client) {
var args = {
merchantAuthentication: {
name: '285tUPuS',
transactionKey: '58JKJ4T95uee75wd'
}
};
client.Service.ServiceSoap12.GetTransactionDetails(args,
function(err, result) {
if (err) {
console.log(err);
} else {
console.log(result.GetTransactionDetailsResult[0].messages);
}
});
});
The node-soap module is converting your JavaScript object to XML before sending the transaction to the server. It wraps the request in an xml element as outlined by the wsdl. Here is an example of what might be produced by node-soap when passing the object you provided (important to note the outer element is created by the node-soap module according to the wsdl):
This example is using the wsdl for the CyberSource API
<data:requestMessage xmlns:data="urn:schemas-cybersource-com:transaction-data-1.93" xmlns="urn:schemas-cybersource-com:transaction-data-1.93">
<data:merchantAuthentication>
<data:name>285tUPuS</data:name>
<data:transactionKey>58JKJ4T95uee75wd</data:transactionKey>
</data:merchantAuthentication>
</data:requestMessage>
Also, I don’t know exactly how the Authorize.net api works, but it sounds like you might want to check out using username token authentication if necessary:
client.setSecurity(new soap.WSSecurity('username’, ‘password’));

Resources