api call from flow

Post Reply
Sunnyland
Member
Posts: 56
Joined: Mon Aug 19, 2013 1:34 am

api call from flow

Post by Sunnyland »

I am currently trying to make an api call from a flow. I already have a script that works using Javascript but for this I have decided to put my poor NodeJs skills to the test and see how I go. I have failed so far, it appears that the http code is just ignored by switch. I do not get success logs or error logs and in debug mode it just jumps over the code.
Below I have shared my code, you will notice I have both http and axios in the code, basically I was just trying both to see if one would work. Originally I just had http but expanded when I could not get it to work.
Help will be appreciated.

const http = require("http");
const axios = require('axios');
const DomPaser = require("xmldom").DOMParser;
const XPath = require("xpath");
const fs = require("fs-extra");

async function jobArrived(s, flowElement, job) {

let jobName = await job.getName();

const tempPath = await job.getDataset("knifedata", AccessLevel.ReadOnly);
const content = await fs.readFile(tempPath, { encoding: "utf8" });

var doc = new DomPaser().parseFromString(content);

var value = await XPath.select("//value",doc);

await job.log(LogLevel.Info, jobName);
let filename = jobName;

let data = JSON.stringify({ details: { "knifenumber": value[0].firstChild.data, "filename": filename, "description1": isEmpty(value[2]), "description2": isEmpty(value[3]), "description3": isEmpty(value[4]), "jobnumber":value[1].firstChild.data} })

let options = {
hostname: "myhost",
port:80,
path: "/api/iq/NewKnife",
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.byteLength(data)
}
}

axios
.post('myhost/api/iq/NewKnife', {
item: data
})
.then(res => {
job.log(LogLevel.Info,"statusCode: %1",[res.statusCode])
job.log(LogLevel.Info,res)
})
.catch(error => {
job.error(LogLevel.Info,error)
})

http.request(options, res => {
job.log(LogLevel.Info,"statusCode: %1",[res.statusCode])
res.on('data', d => {
data += d
})
res.on("end", () => {
console.log(data)
})
.on("error", console.error)
.end(data)
})

await job.sendToSingle();
}

var isEmpty = function(value) {
if (value.firstChild) {
return value.firstChild.data;
}else{
return "";
}
}
freddyp
Advanced member
Posts: 1008
Joined: Thu Feb 09, 2012 3:53 pm

Re: api call from flow

Post by freddyp »

You are using callbacks for the http part, but Switch keeps executing the rest of the script and hits the end before the http call calls the callback function (lots of calling going on here).

We are organizing webinar sessions on NodeJS scripting in Switch on October 20th and 22nd (Getting started) and on November 17th and 19th (Advanced). Keep an eye on your mailbox for the invitations with the times and registration details.

One of the things that will be mentioned several times during these sessions: USE PROMISES!
Sunnyland
Member
Posts: 56
Joined: Mon Aug 19, 2013 1:34 am

Re: api call from flow

Post by Sunnyland »

Thanks Freddy,
Yep big learning curve with NodeJS, using callback or Promises. I really had to drill down on what the differences are. I have change the above code and now it uses promises and not callbacks and believe it or not the code is much simpler and now works.

Will look forward to the webinar.
User avatar
foxpalace
Member
Posts: 33
Joined: Fri Jan 14, 2011 12:25 pm
Location: Germany

Re: api call from flow

Post by foxpalace »

Hi,
can you post, what you changed?
Sunnyland
Member
Posts: 56
Joined: Mon Aug 19, 2013 1:34 am

Re: api call from flow

Post by Sunnyland »

Hi Foxplace,
This is the code I used to send the SOAP request and to return as a promise.

const options = {
hostname: nURL.hostname,
port: 443,
path: path,
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': data.length,
'Host' : nURL.hostname
}
}

return new Promise((resolve, reject) => {
const req = https.request(options, res => {
console.log(`statusCode: ${res.statusCode}`)
let body = '';
res.on('data', (chunk) => (body += chunk.toString()));
res.on('error', reject);
res.on('end', () => {
if (res.statusCode >= 200 && res.statusCode <= 299) {
resolve({statusCode: res.statusCode, headers: res.headers, body: body});
} else {
reject('Request failed. status: ' + res.statusCode + ', body: ' + body);
}
});
});

req.on('error', reject);
req.write(data, 'binary');
req.end();

});

Hope this helps
Sunnyland
Member
Posts: 56
Joined: Mon Aug 19, 2013 1:34 am

Re: api call from flow

Post by Sunnyland »

This is what the above code looks with these changes.

const querystring = require('querystring');
const http = require("http");
const XPath = require("xpath");
const fs = require("fs-extra");
const DomPaser = require("xmldom").DOMParser;

async function jobArrived(s, flowElement, job) {

let jobName = await job.getName();

const tempPath = await job.getDataset("knifedata", AccessLevel.ReadOnly);
const content = await fs.readFile(tempPath, { encoding: "utf8" });

var doc = new DomPaser().parseFromString(content);

var value = await XPath.select("//value",doc) //Get Title and Clean

await job.log(LogLevel.Info, jobName);
let filename = jobName;

let data = JSON.stringify({ details: { "knifenumber": value[0].firstChild.data, "filename": filename, "description1": isEmpty(value[3]), "description2": isEmpty(value[4]), "description3": isEmpty(value[5]), "knifecategory": isEmpty(value[1]), "jobnumber":value[2].firstChild.data} })

try{
await UpdateDieLibary(data);
} catch(e){
console.log(e);
}
await job.sendToSingle();
}

async function UpdateDieLibary(data) {

let options = {
hostname: 'myhost',
port:80,
path: '/api/iq/NewKnife',
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.byteLength(data)
}
}

return new Promise((resolve, reject) => {
const req = http.request(options, res => {
console.log(`statusCode: ${res.statusCode}`)
let body = '';
res.on('data', (chunk) => (body += chunk.toString()));
res.on('error', reject);
res.on('end', () => {
if (res.statusCode >= 200 && res.statusCode <= 299) {
resolve({statusCode: res.statusCode, headers: res.headers, body: body});
} else {
reject('Request failed. status: ' + res.statusCode + ', body: ' + body);
}
});
});

req.on('error', reject);
req.write(data, 'binary');
req.end();
});



}

var isEmpty = function(value) {
if (value.firstChild) {
return value.firstChild.data;
}else{
return "";
}
}
freddyp
Advanced member
Posts: 1008
Joined: Thu Feb 09, 2012 3:53 pm

Re: api call from flow

Post by freddyp »

@Sunnyland: you can make the HTTP part of your code simpler based on the advice I gave in this post: viewtopic.php?f=26&t=3959
Post Reply