nodejs app is not able to connect to REST api nodejs app - node.js

I have a nodejs REST api hosted on localhost and I have a nodejs app that is consuming it. This app too is running on localhost. Everything was working fine but after a restart the webapp just could not connect to the REST api anymore. I am running Windows 10.
I tested the REST api with postman and also with browser, it worked. There is no issue with the REST api.
Tried changing the port numbers - same result.
I ran wireshark to see the difference between when requesting from browser and from nodejs webapp. Below is the screenshot. First two lines are when the nodejs app made the request and the next two are from browser.
I am not able to understand what is wrong here. I tried with a standalone nodejs script, that too failed. Below is the script I used.
var request = require('request');
var u = "xxx";
var p = "xxx";
var auth = "Basic " + new Buffer(u + ":" + p).toString("base64");
var username = "qqqq";
var password = "eeee";
var options = {
url : 'http://localhost:4001/api/v1/transaction',
headers : {
"Authorization" : auth
},
};
console.log(options.url);
request.get(options, function(error,response,body){
//console.log(options);
//console.log(response);
console.log(response.statusCode);
console.log(body);
if (!error && response.statusCode == 200) {
var userObj = JSON.parse(body);
callback(userObj);
} else {
console.log("---- Error ----")
console.log(error);
}
});

I have found the problem and I am posting the answer in the hope that someone would find it useful.
My hint was from the wireshark. (screenshot in the question) All successful requests went to [::1] not localhost or 127.0.0.1. After the reboot of the windows 10 machine, the REST api nodejs app was actually no longer serving on the ip v4 localhost but was serving on ip v6 localhost. There was absolutely no issue with the code.
Instead of using localhost in the url in the consuming webapp, I changed it to [::1] and it started to work.
.....
.....
var options = {
//url : 'http://localhost:4001/api/v1/transaction',
// replaced localhost with [::1]
url : 'http://[::1]:4001/api/v1/transaction',
headers : {
"Authorization" : auth
},
};
.....
.....

Related

Connecting Amazon Alexa to web_lirc, best practice?

I have successfully created demo project where i can control an infrared transmitter using the Amazon Echo Alexa.
Moving forward with my project I'm not sure what the best practices would be in relation to performance and mostly important security. I will explain the project below and elaborate on the issues:
Installed nodejs server on a Raspberry pi running on port 1234
Installed web_lirc to be able to have an nodejs api interface to LIRC
Created an AWS-lambda skill based on the HelloWorld nodejs template with my own simple "hack" working but not pretty :) See code snippet below:
var http = require('http');
var host = '12.34.56.78'; // (no http/https !)
var port = 3000;
var cmd = '';
function performMacroRequest(endpoint, data)
{
cmd = '/macros/' + endpoint;
//console.log('cmd: ' + cmd);
var options = {
host : host,
port : port,
path : cmd, // the rest of the url with parameters if needed
method : 'POST'
};
http.request(options, function(res)
{
console.log('performMacroRequest - STATUS: ' + res.statusCode);
res.on('data', function (chunk)
{
console.log(cmd + ': '+ chunk);
});
}).end();
}
//
var APP_ID = "protected by me"; // Amazon Alexa hardware ID
HelloWorld.prototype.intentHandlers = {
// register custom intent handlers
"HelloWorldIntent": function (intent, session, response)
{
response.tellWithCard("Hello World!", "Hello World", "Hello World!");
},
"IRIntent": function (intent, session, response)
{
performMacroRequest('TESTTV','');
},
"AMAZON.HelpIntent": function (intent, session, response) {
response.ask("You can say hello or cake to me!", "You can say hello or cake to me!");
}
};
The issues as i see them, but are not sure how to address:
The best and most secure way to control my Raspberry web service from AWS. What would be the best option to control external hardware, is that using a webservice and what about protection?
Currently i need to have the port open in my router, so basically everyone with access to my IP could control my raspberry using JSON POST/GET commands. What could be a potential solution, is that to add an overlaying web interface with password protection?
Is it possible to have Alexa talking directly with my hardware on LAN without going trough AWS Lambda?
Overall i think I'm asking for the best practices(technically/security) on having Alexa to access local nodejs server.
Please let me know if anything has to be elaborated or explained in more details.
/Thomas

Skype Bot responding with empty body

I'm trying to get a Skype bot up and running based off of the echo example but I'm struggling to make a successful POST to my app. When I send a post to /v1/chat I get back a status of 201 (successful creation), and nothing in the body. My console.log does not print anything either, which leads me to believe that the botService.on('personalMessage', ...) function is not being run. Does anyone have any insight into how these POST requests should be formatted? I cannot seem to find anything in the documentation.
My code:
const fs = require('fs');
const restify = require('restify');
const skype = require('skype-sdk');
const botService = new skype.BotService({
messaging: {
botId: '28:<bot’s id="ID176db9ab-e313-4d76-a60c-bc2a280e9825">',
serverUrl : "https://apis.skype.com",
requestTimeout : 15000,
appId: process.env.APP_ID,
appSecret: process.env.APP_SECRET
}
});
botService.on('contactAdded', (bot, data) => {
console.log('contact added');
bot.reply('Hello ${data.fromDisplayName}!', true);
});
botService.on('personalMessage', (bot, data) => {
console.log('message incoming');
console.log(data);
bot.reply('Hey ${data.from}. Thank you for your message: "${data.content}".', true);
});
const server = restify.createServer();
server.post('/v1/chat', skype.messagingHandler(botService));
const port = process.env.PORT || 8080;
server.listen(port);
console.log('Listening for incoming requests on port ' + port);
Final Edit & Solution: I think the problem caused by Heroku somehow(it could be something with their free tier ,1 dyno). After some effort, I uploaded the program to Azure, and it is now working perfectly.
Potential Solution: You need to change the server address in the server.post command. If you run your program in "https:\www.yourwebsite.com/v1/chat" , you need to modify this;
server.post('/v1/chat', skype.messagingHandler(botService));
to this;
server.post('https:\\www.yourwebsite.com/v1/chat', skype.messagingHandler(botService));
Of course, don't forget to specify your app id, bot id, and app secret. If you don't have one, you need to generate a password in your Skype application page.
I have the exact problem with the OP. I followed the tutorial, and it doesn't specify how to modify our code to comply with our server. So, after running the program it only returns this;
{"code":"ResourceNotFound","message":"/ does not exist"}
In the Echo example in the Skype Bot Webpage; it says;
"We'll assume the bot's URL for messaging was set to https://echobot.azurewebsites.net/v1/chat during registration."
Make sure that Procfile and worker processes are setup.
My bot is working fine on heroku itself

Automatically restarting Heroku NodeJS app

I have a NodeJS app hosted on Heroku. Is there a way for me to automatically run the "heroku restart" command every hour?
I found this answer but it looks like it's for a Rails project: Restart my heroku application automatically
Yup, use the Heroku SDK for Node.js.
Something like:
heroku.apps('my-app').dynos().restartAll()
Should do the trick. All of the dyno documentation can be found here: https://github.com/heroku/node-heroku-client/blob/master/docs/dyno.md. You can run a scheduled script using the Heroku scheduler.
I must warn you though, this is most certainly not the best way to do whatever you are trying to do. If you provide more insight into your problem I'm sure we can suggest something more appropriate than restarting your dynos all the time.
Using the Heroku v3 API it is possible using the request node module
var token = 'youAPIKeyHere';
var appName = 'yourAppName here';
var dynoName = 'yourDynoHere';
var request = require('request');
request.delete(
{
url: 'https://api.heroku.com/apps/' + appName + '/dynos/',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/vnd.heroku+json; version=3',
'Authorization': 'Bearer ' + token
}
},
function(error, response, body) {
// Do stuff
}
);
There is also a node wrapper that provides a similar experience, but is poorly documented and requires an understanding of the v3 API anyway
var token = 'youAPIKeyHere';
var appName = 'yourAppName here';
var dynoName = 'yourDynoHere';
var Heroku = require('heroku-client');
var heroku = new Heroku({ token: token });
heroku .delete('/apps/' + appName + '/dynos/' + dynoName)
.then( x => console.log(x) );
I also found it useful to experiment in browser with this code
var token = 'youAPIKeyHere';
var appName = 'yourAppName here';
var dynoName = 'yourDynoHere';
var xhr = new XMLHttpRequest();
xhr.open(
'DELETE',
'https://api.heroku.com/apps/' + appName + '/dynos/' + dynoName
);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Accept', 'application/vnd.heroku+json; version=3');
xhr.setRequestHeader('Authorization', 'Bearer ' + token);
xhr.onload = function() {
console.log(xhr.response);
};
xhr.send();
I personally did find using the delete method a bit concerning. Caution should be taken with using the delete method and the /apps/$$appName$$ endpoint alone will delete the app. This is from personal experience
For any of the above, if you omit the dyno name, you will restart all dynos under the app
The other question references a repo that is no longer supported

APISubscriptionError instagram API private network

I'm trying set up a instagram subscription on my localhost with the Instagram-node nodeJs API, but when I launch this code I got this error :
{ [Error: APISubscriptionError: Invalid URL. The URL may be on a private network.]
code: 400,
error_type: 'APISubscriptionError',
error_message: 'Invalid URL. The URL may be on a private network.',
retry: [Function] } undefined
the code :
var express = require('express');
var app = express();
var api = require('instagram-node').instagram();
api.use({access_token : 'xxxxxxxxxxxxxxx'})
api.use({
client_id:'xxxxxxxxxx',
client_secret:'xxxxxxxxxxxxx'
});
var redirect_uri = 'http://127.0.0.1:3000/callback';
api.add_geography_subscription(48.565464564, 2.34656589, 100, 'http://127.0.0.1:3000/callback',
{},
function(err, result, remaining, limit){
console.log(err,result)
});
app.listen(3000);
Any ideas ?
Instagram or anybody esle cannot access your localhost or 127.0.0.1 as this IP address is just known and accessible on your computer itself.
You have to register the callback on a public IP address or domain and host your application there.
I am currently building an app using NodeJS and Instagram Real-time API myself. The answer to this is to use something like http://localtunnel.me/. You could also host your app on something like Heroku as well.
The marked answer is only partially correct.

Receiving data sent from AIR app in node.js server running on Heroku

I am trying to receive data sent from my client adobe air application in node.js server running on Heroku, but with no success.
This is how i am sending the data:
var loader : URLLoader = new URLLoader();
var request : URLRequest = new URLRequest("http://127.0.0.1:5000");
request.method = URLRequestMethod.GET;
loader.dataFormat = URLLoaderDataFormat.TEXT;
var variables:URLVariables = new URLVariables();
variables.data = 'this is data';
request.data = variables;
loader.addEventListener(Event.COMPLETE, onRestaurantObjectLoadComplete);
loader.load(request);
And my Node.js code for receiving requests :
app.get('/',function (request, res) {
console.log("received request data" + request.data );
});
app.listen(port, function() {
console.log("Listening on " + port);
});
The requests come to the server, and i am able to send the answer to the client, but data is always undefined.
Also, if i try to send data using POST method i get a Stream error in AIR application.
What would be the correct way of sending data to node.js server from AIR application?
EDIT: I managed to make it work locally, but when i upload it to heroku, it doesnt work.
I am sending the request to http://: (same as i did locally but myHerokuApp.com was localhost) and i keep getting a stream error.
What would have to be the correct URL to send requests to?
It seems it only does not work on the Simulator, once on testing on a real device it will work with the URL given by Heroku.
Still don't know how to make it work on the Simulator though.

Resources