Socket hang up error on https request to external API? - node.js

I'm receiving a socket hang up error when attempting to access an external API. The external API can be reached manually (click here) and returns results even when using my API key (that's a development API key used to demonstrate the API on the site).
The code I'm using looks like the following. Please note when you see my_api_key the real key exists.
var zipCodeApiPath = '/rest/my_api_key/radius.json/{{zip}}/15/mile';
...
var https = require('https');
...
var options = {
hostname: 'zipcodedistanceapi.redline13.com',
port: 443,
path: zipCodeApiPath.replace('{{zip}}', zipCode),
method: 'GET',
secureProtocol: 'SSLv3_method'
};
options.agent = new https.Agent(options);
console.log(options);
https.request(options, function(res) {
console.log(res);
...
});
When logging out the options to the console I get this:
{ hostname: 'zipcodedistanceapi.redline13.com',
port: 443,
path: '/rest/my_api_key/radius.json/80549/15/mile',
method: 'GET',
secureProtocol: 'SSLv3_method',
agent:
{ domain: null,
_events: { free: [Function] },
_maxListeners: 10,
options: [Circular],
requests: {},
sockets: {},
maxSockets: 5,
createConnection: [Function: createConnection] } }
Why won't it respond?
Code in Progress
Below is the code in progress based off of the answer by mscdex.
var req = https.request(options, function(res) {
var response = '';
res.on('data', function(chunk) {
response += chunk;
});
res.on('end', function() {
var newObj = {
zip: zipCode,
codes: JSON.parse(response).zip_codes
};
coll.insert(newObj, function(err, item) {
if (err) {
callback(err);
}
else {
console.log(item.codes);
callback(null, item.codes);
}
});
});
});
req.end();
req.on('error', function(e) {
console.log(e);
});

There's a couple of things missing here:
You are not calling .end() on your request object so that the request can be sent to the server.
You should read from the response stream.

Related

How to send post request to iotdata service with authorization from a node js lambda function

I have the following post request that works in insomnia, but am not sure how to send it in node js lambda function, specifically I don't know how to do the authorization.
Here is my setup in insomnia
post request
https://obsf-ats.iot.us-east-1.amazonaws.com/things/esp8266_7F3B95/shadow
json
{
"state" :{
"desired":{
"on": true
}
}
}
auth
What I would do, but don't know where to put the auth, I am also not sure where to put the body of the message. Any help would be greatly appreciated.
const https = require('https')
const data = JSON.stringify({
todo: 'Buy the milk'
})
const options = {
hostname: 'https://obsf-ats.iot.us-east-1.amazonaws.com',
port: 443,
path: '/things/esp8266_7F3B95/shadow',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
}
const req = https.request(options, res => {
console.log(`statusCode: ${res.statusCode}`)
res.on('data', d => {
process.stdout.write(d)
})
})
req.on('error', error => {
console.error(error)
})
req.write(data)
req.end()
UPDATE: I have tried the following but it error with no console, is there a way to get the request error
var load = JSON.stringify({
state: {
desired: {
on: false,
},
},
});
request(
aws4.sign(
{
hostname: "https://obsf-ats.iot.us-east-1.amazonaws.com",
service: "iotdata",
region: "us-east-1",
method: "POST",
path: "/things/esp8266_7F3B95/shadow",
headers: {
"Content-Type": "application/x-amz-json-1.0",
},
body: load,
},
{
secretAccessKey: "obsf/obsf/x5Hpej0I",
accessKeyId: "obsf",
}
)
);
UPDATE: I am getting the following error and a 403
etaddrinfo ENOTFOUND https://obsf-ats.iot.us-east-1.amazonaws.com
Had to change this from
hostname: 'https://obsf-ats.iot.us-east-1.amazonaws.com',
to this
hostname: 'obsf-ats.iot.us-east-1.amazonaws.com',

ENOTFOUND when making API call from Azure Functions NodeJS

I am trying to make an API call using Azure Functions. But I am getting below error.
{
"errno": "ENOTFOUND",
"code": "ENOTFOUND",
"syscall": "getaddrinfo",
"hostname": "https://jsonplaceholder.typicode.com",
"host": "https://jsonplaceholder.typicode.com",
"port": "80"
}
My Code
var http = require('http');
module.exports = function (context) {
context.log('JavaScript HTTP trigger function processed a request.');
var options = {
host: 'https://jsonplaceholder.typicode.com',
port: '80',
path: '/users',
method: 'GET'
};
// Set up the request
var req = http.request(options, (res) => {
var body = "";
res.on("data", (chunk) => {
body += chunk;
});
res.on("end", () => {
context.res = body;
context.done();
});
}).on("error", (error) => {
context.log('error');
context.res = {
status: 500,
body: error
};
context.done();
});
req.end();
};
How could I solve this?
You made a few common mistakes:
You are using http module for https URL.
Change host value to jsonplaceholder.typicode.com
For https protocol port should be 443
Change options as below:
For http:
var options = {
host: 'jsonplaceholder.typicode.com',
port: '80',
path: '/users',
method: 'GET'
};
For https:
Use https module to make request and options object should be like this
var options = {
host: 'jsonplaceholder.typicode.com',
port: '443',
path: '/users',
method: 'GET'
};
Demo:https://repl.it/repls/RepentantGoldenrodPriority

Node.js post request not executing callback

So ive got this function:
async function getRandomNumber(){
const https = require('https');
const url = 'https://api.random.org/json-rpc/2/invoke';
const params:object = {
"jsonrpc": "2.0",
"method": "generateIntegers",
"params": {
"apiKey": process.env.randomApiKey,
"n": 1,
"min": 1,
"max": 10,
},
"id": 42
}
const options = {
hostname: 'https://api.random.org',
port: 443,
path: '/json-rpc/2/invoke',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(JSON.stringify(params))
}
};
const req = https.request(options, (res:any) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf8');
res.on('data', (chunk:any) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e:any) => {
console.error(`problem with request: ${e.message}`);
});
// Write data to request body
req.write(JSON.stringify(params));
req.end();
}
which is being called like this:
await getRandomNumber();
But the call back does not log anything, so it seem that the post request is not beeing executed? How can I make this work?
Is it better to use the request module?
The problem is that you are trying to await a callback style function which doesn't return a promise. You need to return a promise to await it.
Regarding request module, i wouldn't suggest using it as it is not maintained. You can read more here
https://github.com/request/request/issues/3142
This also talks about alternative libraries
https://github.com/request/request/issues/3143
One of the library is got which can simplify the work which are doing. the code will look like
const getResponse = await got("http://someurlhere");
console.log(getResponse.body);

One Signal Push Notification

How to include small icon and big icon url while creating a push notification in node js, I know that we need to send image url while sending push notification, i need code sample in node js.. I have this code..
sendNotificationToSpecific =function (token,messages) {
var sendNotification = function (data) {
var headers = {
"Content-Type": "application/json; charset=utf-8",
"Authorization": "Basic MDNlMTNjYWMTgy"
};
var options = {
host: "onesignal.com",
port: 443,
path: "/api/v1/notifications",
method: "POST",
headers: headers
};
var https = require('https');
var req = https.request(options, function (res) {
res.on('data', function (data) {
console.log("Response:");
console.log(JSON.parse(data));
});
});
req.on('error', function (e) {
console.log("ERROR:");
console.log(e);
});
req.write(JSON.stringify(data));
req.end();
};
var message = {
app_id: "awer342-d744-4787-b59a-f55c6215c491",
contents: {"en": messages},
include_player_ids: [token],
};
sendNotification(message);
};
As you can see in the docs https://documentation.onesignal.com/reference#section-appearance you can simply extend your message object like
var message = {
app_id: "xxxx",
contents: {"en": messages},
include_player_ids: [token],
small_icon: "resource_name", // can not be an url
large_icon: "http://url/ or resource_name"
}

Node SOAP client to connect to InDesign Server

I am trying to get node/express to send soap request to indesign server.
Posting the request from Soap.ui or Postman works fine. Loading the "soap" page in the browser errors.
I also tried the node client with a few sample scripts from the new and they work, so the install should be OK.
This is what I have so far:
router.get('/soap', function(req, res, next) {
var url = 'http://<server_ip>:8088/service?wsdl';
var args = { "IDSP:RunScriptParameters" :
{ 'scriptLanguage': 'javascript',
'scriptFile': 'C:/indesign_scripts/test.jsx'
}
};
soap.createClient(url, function(err, client){
client.Service.Service.RunScript(args, function(err, result) {
if (err) console.log(err);
console.log(result);
});
});
client.describe() returns:
{ Service:
{ Service:
{ RunScript: [Object],
BeginSession: [Object],
EndSession: [Object] } } }
I am trying to use RunScript object.
client.describe().Service.Service.RunScript:
{ input:
{ runScriptParameters:
{ scriptText: 'xsd:string',
scriptLanguage: 'xsd:string',
scriptFile: 'xsd:string',
'scriptArgs[]': [Object],
targetNSAlias: 'IDSP',
targetNamespace: 'http://ns.adobe.com/InDesign/soap/' } },
output:
{ errorNumber: 'xsd:int',
errorString: 'xsd:string',
scriptResult:
{ data: 'xsd:anyType',
targetNSAlias: 'IDSP',
targetNamespace: 'http://ns.adobe.com/InDesign/soap/' } } }
Console shows this error:
[Error: connect ECONNREFUSED 127.0.0.1:8088]
code: 'ECONNREFUSED',
errno: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 8088 }
Indesign Server wsdl could be viewed here:
https://gist.github.com/tomtaylor/1034317
I suspect this is something with args variable format.
You can fix this issue by adding line below
client.setEndpoint('http://<server_ip>:8088');
I tried to add "Access-Control-Allow-Origin" to my headers in my app file, as suggested by #Chirdeep Tomar, but I am still getting the same errors.
The workaround I came up with was to use http request or curl for ajax post.
The example with request:
var express = require('express');
var request = require('request');
var parser = require('xml2json');
var router = express.Router();
router.get('/ProductionBooks/:id', function(req, res) {
var myId = req.params.id;
var myBody = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://ns.adobe.com/InDesign/soap/"><soapenv:Body>'
+'<soap:RunScript>'
+'<runScriptParameters>'
+'<scriptLanguage>javascript</scriptLanguage>'
+'<scriptFile>C:/indesign_scripts/test.jsx</scriptFile>'
+'</runScriptParameters>'
+'</soap:RunScript>'
+'</soapenv:Body>'
+'</soapenv:Envelope>';
request({
url: 'http://192.168.0.129:8088', //URL to hit
method: 'POST',
headers: {
'Content-Type': 'application/xml',
'Content-Length': Buffer.byteLength(myBody)
},
body: myBody
}, function(error, response, body){
if(error) {
console.log(error);
} else {
console.log(response.statusCode + '\n');
var objJSON = JSON.parse(parser.toJson(body));
console.log(objJSON['SOAP-ENV:Envelope']['SOAP-ENV:Body']['IDSP:RunScriptResponse'].errorNumber);
}
});
res.end();
});
Example with curl:
var curl = require("curl");
curl.post(url, soapBody, options, function(err, response, body) {
try {
console.log(response.body);
}
catch (err) {
console.log(err);
}
});
res.end();
});
using easy-soap-request:
const soapRequest = require('easy-soap-request');
const url = 'http://[YOUR SERVER ADDRESS]:[IDS PORT]/service?wsdl';
const sampleHeaders = {
'user-agent': 'sampleTest',
'Content-Type': 'text/xml;charset=UTF-8',
};
const xml = '<?xml version="1.0" encoding="UTF-8"?>'
+'<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:IDSP="http://ns.adobe.com/InDesign/soap/">'
+'<SOAP-ENV:Body><IDSP:RunScript><IDSP:runScriptParameters>'
+'<IDSP:scriptLanguage>javascript</IDSP:scriptLanguage>'
+'<IDSP:scriptFile>[PATH TO SCRIPTS]/Hello.jsx</IDSP:scriptFile>'
+'<IDSP:scriptArgs><IDSP:name>myArg</IDSP:name><IDSP:value>Test Value</IDSP:value></IDSP:scriptArgs>'
+'</IDSP:runScriptParameters></IDSP:RunScript>'
+'<IDSP:RunScriptResponse><errorNumber>0</errorNumber><scriptResult><data xsi:type="IDSP:List"><item><data xsi:type="xsd:string">1</data></item></data></scriptResult></IDSP:RunScriptResponse>'
+'</SOAP-ENV:Body></SOAP-ENV:Envelope>';
// usage of module
(async () => {
const { response } = await soapRequest({ url: url, headers: sampleHeaders, xml: xml, timeout: 1000 }); // Optional timeout parameter(milliseconds)
const { headers, body, statusCode } = response;
console.log(headers);
console.log(body);
console.log(statusCode);
})();
Sample script (hello.jsx):
var arg = app.scriptArgs.get("myArg");
var res = "Your input: " + arg;
res;

Resources