how to consume wcf in node.js? - node.js

I want to consume wcf in node.js. I tried it:
soap.createClient(url, function (err, client) {
if (err) {
console.log(err);
return false;
}
client.myFunc(args, function(err1, result) {
if(result.success)
return true;
});
});
But an error occurred in createClient (error block). it says: Unexpected root element of WSDL or include .
Then I tried by wcf.js:
var BasicHttpBinding = require('wcf.js').BasicHttpBinding
, Proxy = require('wcf.js').Proxy
, binding = new BasicHttpBinding()
, proxy = new Proxy(binding, " http://localhost/myService.svc");
var message = '<Envelope xmlns=' +
'"http://schemas.xmlsoap.org/soap/envelope/">' +
'<Header />' +
'<Body>' +
'<myFunc xmlns="http://localhost/myService.svc/">' +
'<value>'+ args +'</value>' +
'</AddNewUser>' +
'</Body>' +
'</Envelope>';
proxy.send(message, "http://localhost/myService.svc", function (result, ctx){
if(result.success)
return true;
});
But my program didn't call send function.
Finally I tried to configure WCF to WSDL publishing like this: WCF cannot configure WSDL publishing
But it didn't work to! How can I solve my problem?

I ran into this and in my case it's because the response is gzipped. The npm package soap does specify 'Accept-Encoding': 'none' but the SOAP server (developed by my company) is not well behaved and sends back a gzipped body. The soap package doesn't handle this.
One alternative I'm looking at is to pass my own httpclient in the options parameter of createClient and unzip it. There is an example of using a custom httpclient in the tests for the node-soap code on GitHub: https://github.com/vpulim/node-soap/blob/master/test/client-customHttp-test.js.
I haven't worked out how to unzip the response yet, but I'll update this answer once I work it out.
Update
For gzipped responses, it's simpler. You can pass any options you want to the node request call in the wsdl_options property of the createClient options object. This includes gzip: true, which will make request handle gzipped requests for you. e.g.
soap.createClient('http://someservice.com/?wsdl',
{ wsdl_options: { gzip: true } },
function (err, client) {});
Then when making SOAP method calls, add the gzip parameter to the options argument after your callback e.g.
client.someSoapCall({arg1:"12345"},
function (err, result) {},
{ gzip: true });
I figured this out by digging into the node soap code. The docs do not explicitly mention these things.

Related

How to download a multipart wav file from cloudant database and save locally using Node JS and REST API?

I am stuck in retrieving multipart from cloudant using Node JS API. Hence, I used REST API to download the wav file from cloudant database. But its not downloading wav file from https URL. When I enter the https URL directly in browser, it prompts me to save file locally. So, the URL is correct.
Here is the code for REST API:
var request1 = require('request');
var filestream = fs.createWriteStream("input.wav");
var authenticationHeader = "Basic " + new Buffer(user + ":" + pass).toString("base64");
request1( { url : "example.com/data/1533979044129/female";, headers : { "Authorization" : authenticationHeader } },
function (error, httpResponse, body) {
const statusCode = httpResponse.statusCode;
httpResponse.pipe(filestream);
httpResponse.on('end', function () {
console.log("file complete");
filestream.close();
}); });
The file size of input.wav is 0. Its not downloading file. Please help.
Your callback has an error argument, which you are completely ignoring. Do something with this error, like print it out so your problem can tell you what you're doing wrong. I definitely see at least 1 problem in your source, and the error from request should tell you what it is.
Edit On second thought the above code shouldn't even execute. You should share code that you tested yourself. There's typos in there.

How to stub SOAP client request with sinon in Node JS?

I am using strong-soap module to get data from SOAP request.
var soap = require('strong-soap').soap;
soap.createClient(url, options, function (err, client) {
var method = client.GetInfoSOAP;
method(requestQuery, function (err, info) {
// bla bla
}
}
I am getting the required data. Now
I want to write unit test case to mock the SOAP request using sinon stub, but didn't get any success. Any help would be appreciated.
What you want is controlling the soap object's createClient. You can do that using techniques that fall into one of two categories:
Dependency injection - expose a setter through which you can inject a fake module you control yourself for testing
Using link seams - hook into the import/require mechanism and override what the module is getting.
The Sinon project has a nice page on using link seams through proxyquire, and I have also detailed how to do DI on the issue tracker.
To achieve the first, all you need is to do something like this in the module:
module.exports._injectSoap = (fake) => soap = fake;
Then in your test code:
const fakeSoap = { createClient : sinon.stub().returns(/* ? */) }
myModule._injectSoap(fakeSoap);
...
assert(fakeSoap.createClient.calledOnce);
assert(...)
Hi i have solved my problem with the following code :
sinon.stub(soap, 'createClient').yields(null, {
GetInfoSOAP: function (request, cb) {
return cb(null, myDesiredData);
}
});

how to restrict making http calls from aws lambda

I am creating application which takes nodejs code from the user, and I am creating lambda function on the fly using that code.
eg: The code can be
var http = require('http');
exports.handler = function(event, context) {
console.log('start request to ' + event.url)
http.get('http://##someapi', function(res) {
console.log("Any Response : " + res.statusCode);
}).on('error', function(e) {
console.log("Error from API : " + e.message);
});
console.log('end request to ' + event.url)
context.done(null);
}
But some how I want to restrict http/https calls to be made from that code , as I don't have control on what code will passed by the user.
So is there any way to restrict that, like some sort of ROLE or POLICY or any configuration to achieve that?
I am able to restrict DynamoDB access by specifying Policy in Role. So I have control over db access but not http calls.
Simply prepend the user's code with the following:
(function(){
function onlyAWS (module) {
var isAWS = /amazonaws.com$/i
var orig = module.request
module.request = function restrictedRequest (opts, done) {
if (typeof opts === 'string') opts = require('url').parse(opts)
if (isAWS.test(opts.host || opts.hostname)) {
return orig.call(module, opts, done)
} else {
throw new Error('No HTTP requests allowed')
}
}
}
onlyAWS(require('http'))
onlyAWS(require('https'))
})()
One alternative would be, putting these lambdas in a VPC with restricted Outbound access.
It sounds like funny solution but I found simple solution to my problem. I am adding below code along with code entered by User.
var require = function(){
return "You are not allowed to do this operation";
}
Now if used user tries to include any 3rd party library like required('http') , then it will not allow to instantiate http lib in the node code.
using this solution I am able to block loading all 3rd party library which i don't want User to use in AWS lambda function.
I am still searching for proper solution instead of using that hack in code.

check on server side if youtube video exist

How to check if youtube video exists on node.js app server side:
var youtubeId = "adase268_";
// pseudo code
youtubeVideoExist = function (youtubeId){
return true; // if youtube video exists
}
You don't need to use the youtube API per-se, you can look for the thumbnail image:
Valid video = 200 - OK:
http://img.youtube.com/vi/gC4j-V585Ug/0.jpg
Invalid video = 404 - Not found:
http://img.youtube.com/vi/gC4j-V58xxx/0.jpg
I thought I could make this work from the browser since you can load images from a third-party site without security problems. But testing it, it's failing to report the 404 as an error, probably because the content body is still a valid image. Since you're using node, you should be able to look at the HTTP response code directly.
I can't think of an approach that doesn't involve making a separate HTTP request to the video link to see if it exists or not unless you know beforehand of a set of video IDs that are inactive,dead, or wrong.
Here's an example of something that might work for you. I can't readily tell if you're using this as a standalone script or as part of a web server. The example below assumes the latter, assuming you call a web server on /video?123videoId and have it respond or do something depending on whether or not the video with that ID exists. It uses Node's request library, which you can install with npm install request:
var request = require('request');
// Your route here. Example on what route may look like if called on /video?id=123videoId
app.get('/video', function(req, response, callback){
var videoId = 'adase268_'; // Could change to something like request.params['id']
request.get('https://www.youtube.com/watch?v='+videoId, function(error, response, body){
if(response.statusCode === 404){
// Video doesn't exist. Do what you need to do here.
}
else{
// Video exists.
// Can handle other HTTP response codes here if you like.
}
});
});
// You could refactor the above to take out the 'request.get()', wrap it in a function
// that takes a callback and re-use in multiple routes, depending on your problem.
#rodrigomartell is on the right track, in that your check function will need to make an HTTP call; however, just checking the youtube.com URL won't work in most cases. You'll get back a 404 if the videoID is a malformed ID (i.e. less than 11 characters or using characters not valid in their scheme), but if it's a properly formed videoID that just happens to not correspond to a video, you'll still get back a 200. It would be better to use an API request, like this (note that it might be easier to use the request-json library instead of just the request library):
request = require('request-json');
var client = request.newClient('https://www.googleapis.com/youtube/v3/');
youtubeVideoExist = function (youtubeId){
var apikey ='YOUR_API_KEY'; // register for a javascript API key at the Google Developer's Console ... https://console.developers.google.com/
client.get('videos/?part=id&id='+youtubeId+'&key='+apikey, function(err, res, body) {
if (body.items.length) {
return true; // if youtube video exists
}
else {
return false;
}
});
};
Using youtube-feeds module. Works fast (~200ms) and no need API_KEY
youtube = require("youtube-feeds");
existsFunc = function(youtubeId, callback) {
youtube.video(youtubeId, function(err, result) {
var exists;
exists = result.id === youtubeId;
console.log("youtubeId");
console.log(youtubeId);
console.log("exists");
console.log(exists);
callback (exists);
});
};
var notExistentYoutubeId = "y0srjasdkfjcKC4eY"
existsFunc (notExistentYoutubeId, console.log)
var existentYoutubeId = "y0srjcKC4eY"
existsFunc (existentYoutubeId, console.log)
output:
❯ node /pathToFileWithCodeAbove/FileWithCodeAbove.js
youtubeId
y0srjcKC4eY
exists
true
true
youtubeId
y0srjasdkfjcKC4eY
exists
false
false
All you need is to look for the thumbnail image. In NodeJS it would be something like
var http = require('http');
function isValidYoutubeID(youtubeID) {
var options = {
method: 'HEAD',
host: 'img.youtube.com',
path: '/vi/' + youtubeID + '/0.jpg'
};
var req = http.request(options, function(res) {
if (res.statusCode == 200){
console.log("Valid Youtube ID");
} else {
console.log("Invalid Youtube ID");
}
});
req.end();
}
API_KEY is not needed. It is quite fast because there is only header check for statusCode 200/404 and image is not loaded.

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