Trying to make a get request using NodeJS - javascript

I am trying to make a get request to my NodeJS server side but it keeps saying CERT_UNTRUSTED.
The code that I am using on the client side is:
function validateUser(){
var userEmail = $("#userEmail").val();
var userPassword = $("#userPassword").val();
$.ajax({
url: "https://changelog.twvending.net/ValidateUserByName?userName="+userEmail+"&userPassword="+userPassword,
success: function(user){
if (user === "bad user"){
alert("Your credentials are incorrect, please try again");
} else {
if (user.User.PermissionLevel === 3){
localStorage.setItem("permission", "hello");
$("#newEntry").show();
window.location.href = "https://changelog.twvending.net";
}
else {
alert("You do not have permission to make new entries");
window.location.href = "https://changelog.twvending.net";
}
}
},
error: function(xhr,status,error){
}
});
}
and on the server side
app.get('/ValidateUserByName', function (req, res) {
res.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin"));
var userEmail = req.query.userName;
var userPassword = req.query.userPassword;
processInput(userEmail +" logged in");
var request = require('request');
request.get('https://32market.com/32marketpcitest/threesquaremarketrest.svc/ValidateUserByEmailULR?email='+userEmail+'&password='+userPassword,
function (err, resp, body) {
if (err){
processInput ( err )
console.log('Error: ' + err);
return;
}
try {
var user = JSON.parse(body);
res.send(user);
}
catch(err) {
processInput('error logging in: invalid user name or password');
res.send("bad user");
}
});
});
My question is what am i missing that the client or sever is not liking. I should also note that this is my first time doing a project like this.

My guess is you don't have the required Or expired ssl certificates to do your request. Probably to 32market.com does it use an https connection? Is it your own site?
You can try adding
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
Before your request
But that isn't exactly secure.

Related

NodeJs Assertion failed on HTTP call (Mac)

var client = require('http');
var endpoint = apiEndpoint;
var request = client.get(endpoint, function(responseFromApi) {
var responseString = '';
responseFromApi.setEncoding('utf-8');
responseFromApi.on('data', function(data) {
responseString += data;
});
// To reformat the string response into Json...
responseFromApi.on('end', function() {
var jsonResponse = JSON.parse(responseString);
callback(jsonResponse);
});
});
I am making API calls using the method above, however on random instances my call fails due to the Assertion fail like below. Anyone has any idea how to fix this?
Assertion failed: (handle->type == UV_TCP || handle->type == UV_TTY || handle->type == UV_NAMED_PIPE), function uv___stream_fd, file ../deps/uv/src/unix/stream.c, line 1568.
Environment: Mac, Nodejs
Note: I have tested the same code on an AWS lambda server and never faced this issue. I am guessing this is a Mac only instance. Lord Google informed me that it is a Mac desync issue.
Same is true if trying to get data from a dynamoDB sitting on Amazon server using the code below...
// To get userID.
var userId = getUserIdFromContext(this);
if (!userId) {
callback('userId is not set.');
}
// To get table name.
var table = constants.dynamoDBTableName;
if(!table) {
callback('DynamoDB Table name is not set.');
}
// To set the DocumentClient.
if(!doc) {
doc = new aws.DynamoDB.DocumentClient({apiVersion: '2012-08-10'});
}
// To set the params.
var params = {
Key: {
CustomerId: userId
},
TableName: table,
ConsistentRead: true
};
// To get data from table.
var skillContext = this;
doc.get(params, function(err, data){
if(err) {
console.log('get error: ' + JSON.stringify(err, null, 4));
callback(err);
} else {
if(isEmptyObject(data)) {
callback('The object is empty.');
} else {
var userData = JSON.parse(data.Item['Data']);
extractUserData(skillContext, userData, callback);
}
}
});
}

Telegram API returning HTML instead of JSON

I'm writing a telegram bot to report fail2ban bans. It's very simple and dirty, written hastily, but it can be used to report any message to a single telegram user:
var TelegramBot = require('node-telegram-bot-api');
var fs = require('fs');
var store = {
get: function (key) {
return fs.readFileSync(__dirname + '/' + key, { encoding: 'utf-8' });
},
set: function (key, value) {
fs.writeFileSync(__dirname + '/' + key, value, { encoding: 'utf-8' });
}
};
var token = store.get('token');
var args = process.argv.slice(2);
if (args.length == 0) {
console.error('No mode specified');
process.exit(0);
}
TelegramBot.prototype.unregisterText = function (regexp) {
for (var i = 0; i < bot.textRegexpCallbacks.length; ++i) {
if (bot.textRegexpCallbacks[i].regexp.toString() == regexp) {
bot.textRegexpCallbacks.splice(i, 1);
return;
}
}
};
fs.appendFileSync(__dirname + '/logs',
'[' + (new Date().toISOString().replace(/T/, ' ').replace(/\..+/, '')) + '] '
+ args.join(' ') + '\n',
{ encoding: 'utf-8' });
switch (args[0]) {
case 'setup':
var bot = new TelegramBot(token, { polling: true });
var step = 'none';
bot.onText(/\/setup/, function (msg, match) {
var fromId = msg.from.id;
step = 'setup-started';
bot.sendMessage(fromId, 'Starting setup. Please enter the verification key.');
bot.onText(/(.+)/, function (msg, match) {
if (step == 'setup-started') {
var key = match[1];
var verification = store.get('key');
if (key == verification) {
store.set('owner', msg.from.id);
step = 'verified';
bot.sendMessage(msg.from.id, 'Correct. Setup complete.');
} else {
step = 'none';
bot.unregisterText(/(.+)/);
bot.sendMessage(msg.from.id, 'Wrong. Setup aborted.');
}
}
});
});
break;
case 'report':
var bot = new TelegramBot(token, { polling: false });
var owner = store.get('owner');
var subject = args[1];
if (subject == 'message') {
var message = args.slice(2).join(' ');
bot.sendMessage(owner, message);
} else if (subject == 'file') {
var content = fs.readFileSync(args[2], { encoding: 'utf-8' });
bot.sendMessage(owner, content);
}
break;
default:
console.error('Unrecognized mode', args[0]);
break;
}
On my developer machine it works fine. I invoke:
node bot.js report message whatever message i want
And I correctly received "whatever message i want" on telegram. However, once I gitted it on my digitalocean vps, it no longer worked. It turns out the problem is with the telegram library:
Unhandled rejection Error: Error parsing Telegram response: <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Bots: An introduction for developers</title>
...
Which apparently returns an html page instead of json... I also tried to contact the same endpoint (api.telegram.org/bothash/sendMessage) with curl on my vps and it returned json (with an error message because i didnt send any parameters, but still json).
I cannot fathom why this happens. Any help?
It seems like either you don't have a file with token on your VPN or the token is incorrect.
You can check it by yourself:
When you make a request to api.telegram.org/{token}/sendMessage, and {token} is incorrect, it redirects you to this page, which responds with HTML you've mentioned in your question.
So you have to debug a behavior of your store.get and store.get functions along with files and tokens to make sure you are using a correct one.
Also, I'd recommend to run bot.getMe() before using any other Telegram API methods to ensure you specified a correct bot token.

Node.js - load data and then hit urls - async

I am new at node.js, so please be patient :)
What I need to do:
load from url Ids of users
Hit another url for every ID
What am I doing wrong?
var http = require('http');
var Client = require('node-rest-client').Client;
var client = new Client();
url = 'http://example.com/api/get-users';
client.get(url, function (data, response) {
if (data.status == 'OK') {
users = data.users;
users.forEach(function(item) {
newUrl = 'http://example.com/generateStats/' + item;
client.get(newUrl, function(data, response){
console.log(data);
});
});
}
});
The value of users is: [1,2,4,5,7,...]
Nothing in forEach is executing, why?
There is no status in data nor response so it never go inside the if block. To handle errors with node-rest-client, you have to listen to the error event:
var http = require('http');
var Client = require('node-rest-client').Client;
var client = new Client();
url = 'http://example.com/api/get-users';
client.get(url, function(data, response) {
// if there is an error, this function is not executed
var users = data.users;
users.forEach(function(item) {
newUrl = 'http://example.com/generateStats/' + item;
client.get(newUrl, function(data, response) {
console.log(data);
});
});
}).on('error', function(err) {
console.log('something is wrong: ' + err.code);
});
There is a response.statusCode though, it returns an http code like 200.
I think you need something like async
Check this answer: simplest-way-to-wait-some-asynchronous-tasks-complete-in-javascript

How to load a specific session using express-session in node.js?

I need to create a websocket where I can connect to it from a different domain (websocket runs on 10.0.4.18:8020 and the client will establish connection from 10.0.4.160:443.)
Each user must have a unique session to be able to reuse his/her user data after authentication takes place.
Since the client "aka user's browser" is on a different host, I am having hard time keeping the session tied with with the client that creates it on page reloaded event!
I thought of this workaround to solve this problem
Create session using XMLHttpRequest() function from the client, then return a sessionID to the client
Save the sessionId in the user's browser using localStorage
Pass the sessionId to socket.io every time a user connects to the websocket.
Websocket then takes the sessionId and reloads it to make it available all over again.
To eliminate session fixation attack, I am going to add few more validation step to make sure the sessionId is not hijacked by using the client's IP and agent data.
Additionally, I need to fire a setInterval() method which will make external API call every second and updates the session variable.
Question
How can I properly reload a session data where I can auto save the variables without having to directly use store.get() to load the session data and save them?
Here is what I have done
I created the session using a file system. On every request I have to load the session store using store.get() method, update the session data, and then save it. But the problem that I have is every time I want to update the session as you can see my below code.
Here is what I have done!
var app = require('express')(),
https = require('https'),
fs = require('fs'),
session = require('express-session'),
fileStore = require('session-file-store')(session),
base64url = require('base64url'),
bodyParser = require("body-parser");
cookieParser = require("cookie-parser"),
env = require('./modules/config');
var server = https.createServer(
{
key: fs.readFileSync('certs/key.pem'),
cert: fs.readFileSync('certs/cert.pem')
}, app).listen(env.socket.port, env.socket.host, function () {
console.log('\033[2J');
console.log('Websocket is running at https://%s:%s', server.address().address, server.address().port);
});
var io = require('socket.io')(server);
var icwsReq = require('./modules/icws/request.js'),
icwsConn = require('./modules/icws/connection.js'),
icwsInter = require('./modules/icws/interactions.js'),
sessionValidator = require('./modules/validator.js');
var icwsRequest = new icwsReq();
var sessionChecker = new sessionValidator();
var sessionStoreFile = new fileStore({path: './tmp/sessions'});
var sessionOptions = {
store: sessionStoreFile,
secret: env.session.secret,
saveUninitialized: true,
resave: false,
cookie: {
path: '/',
httpOnly: true,
maxAge: 60 * 60 * 1000,
secure: true
}
};
app.use(session(sessionOptions)); // session support for the app
app.use(bodyParser.urlencoded({ extended: false })); //allows to pupulate req.body in the REST/PUT post requests!
// Set access control headers on every express route.
app.use(function (req, res, next){
res.setHeader('x-powered-by', 'Express');
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST');
next();
});
//Middleware for authorizing a user before establishing a connection
io.use(function(req, next) {
var sessionID = req.handshake.query.token || '';
var token = req.handshake.query.auth || '';
var origin = req.handshake.headers.origin;
var ip = req.request.socket.remoteAddress;
var userAgent = req.handshake.headers['user-agent'];
if(!sessionID || !token){
console.log('No Session found with this token! ' + sessionID);
return next(new Error('No Session found with this token!'));
}
sessionStoreFile.get(sessionID, function(err, session){
// session updated
if(err){
console.log(err);
return next(new Error(err));
}
if(!session){
console.log('Session Could not be loaded');
return next(new Error('Session Could not be loaded'));
}
if( session.token != token
|| session.ip != ip
|| session.agent != userAgent
|| session.origin != origin
){
session.token = null;
session.ip = null;
session.agent = null;
session.origin = null;
sessionStoreFile.set(sessionID, session);
console.log('This session is invalid! Please sign in');
return next(new Error('This session is invalid! Please sign in'));
}
next();
});
});
io.on('connection', function (socket) {
var sessionID = socket.handshake.query.token;
//load the session with the ID sessionID
sessionStoreFile.get(sessionID, function(err, session){
//add the socket.id to the queue
session.clients.push(socket.id);
//Save the session data after adding the connection to the queue
sessionStoreFile.set(sessionID, session, function(){
//Get the current session data "including current socket.id"
sessionStoreFile.get(sessionID, function(err, session){
//get an instance of icws connector
icwsRequest.setConnection(session.icwsHost, session.icwsPort);
var interactions = new icwsInter(icwsRequest);
//Call the API everysecond, update the session then save the session
setInterval(function(){
sessionStoreFile.get(sessionID, function(err, session){
//call the API and return the new data
session.queue = interactions.updateQueue();
//save the new data every second
sessionStoreFile.set(sessionID, session);
}
}, 1000);
//handle ICWS interactions
socket.on('interaction', function(data){
var task = data.task || '',
phone = data.phone || '',
interactionId = data.interactionId || '',
queueName = data.queueName || '';
//Place a phone call
if(task == 'call'){
interactions.call(phone);
}
//External transfer
if(task == 'eBlindTransfer'){
interactions.blindTransferCallExternal(interactionId, phone);
}
//Internal Transfer
if(task == 'iBlindTransfer'){
interactions.blindTransferCallInternal(interactionId, queueName);
}
});
//send a chat message to all browser's tabs associated with the currect session
socket.on('chat', function(msg){
var clients = session.clients;
console.log(clients);
for (var i in clients) {
var socketId = clients[i];
console.log('Client Said: ' + msg + ' socket Id: ' + socketId);
io.to(socketId).emit('chat', {message: 'Server Said: ' + msg});
}
});
//handle disconnect
socket.on('disconnect', function(msg){
var index = session.clients.indexOf(socket.id);
if(index > -1){
session.clients.splice(index, 1);
//save session after removing a client
sessionStoreFile.set(sessionID, session, function(error){
if(!error){
console.log('Closing tabs: ' + socket.id);
console.log(session);
}
});
}
});
//handle errors
socket.on('error', function(msg){
console.log('Error Message: ' + msg);
});
});
});
});
});
app.get('/', function (req, res) {
res.send('welcome: ' + req.sessionID);
});
app.get('/handshake/:token', function (req, res) {
var origin = req.headers.origin;
var ip = req.connection.remoteAddress;
var userAgent = req.headers['user-agent'];
if(!req.params || !req.params.token || !ip || !origin || !userAgent){
console.log('Missing Request!');
return false;
}
if(!originIsAllowed(origin)){
console.log('This is a cross-domain attack!');
return false;
}
req.session.token = req.params.token;
req.session.ip = ip;
req.session.origin = origin;
req.session.agent = userAgent;
req.session.clients = [];
req.session.save(function(err){
if (err) {
connectionError(res, session);
} else {
res.json({
token: req.sessionID
});
}
});
});
function originIsAllowed(origin) {
// put logic here to detect whether the specified origin is allowed.
var allowed = env.session.allowedOrigins || []
if(allowed.indexOf(origin) >= 0){
return true;
}
return false;
};

Is it possible to catch the exception generated by trying to connect to a bad url?

using node http package it doesn't seem possible to catch the exception caused by opening a bad URL. This is a problem, because it kills my cluster, which I'd like to guarantee will live forever
Here's the code: (uses fibers.promise)
function openConnection(dest, port, contentType, method, throwErrorOnBadStatus)
{
"use strict";
assert.ok(dest, "generalUtilities.openConnection: dest is null");
//dest = dest.replace('//','/');
console.log('opening connection: ' + dest + " contentType: " + contentType);
var prom = promise(),
errProm = promise(),
ar = [],
urlParts = url.parse(dest),
httpClient,
req,
got,
res;
//console.log('urlParts.port: ' + urlParts.port);
if (port) {
urlParts.port = port;
} else if (!urlParts.port) {
urlParts.port = 80;
}
if (contentType) {
urlParts.accept = contentType;
} else {
urlParts.contentType = 'text/html';
}
if (!urlParts.method) {
if (method) {
urlParts.method = method;
} else {
urlParts.method = 'GET';
}
}
try {
httpClient = http.createClient(urlParts.port, urlParts.hostname);
req = httpClient.request(urlParts.method, urlParts.path, urlParts);
//console.log('req: ' + req);
//if (req.connection) {
// req.connection.setTimeout(HTTP_REQUEST_TIMEOUT);
//}
//else {
// throw new Error ("No Connection Established!");
//}
req.end();
req.on('response', prom);
req.on('error', errProm);
got = promise.waitAny(prom, errProm);
if (got === errProm) {
//assert.ifError(errProm.get(), HTTP_REQUEST_TIMEOUT_MSG + dest);
throw new Error(HTTP_REQUEST_TIMEOUT_MSG + dest + ': ' + got.get());
}
res = prom.get();
ar.res = res;
ar.statusCode = res.statusCode;
if (ar.statusCode >= 300 && throwErrorOnBadStatus) {
assert.ifError("page not found!");
}
return ar;
}
catch (err) {
console.log(err);
}
}
and here's how I tested it
var promise = require('fibers-promise');
var gu = require("../src/utils/generalutilities.js");
var brokenSite = 'http://foo.bar.com:94//foo.js';
promise.start(function () {
try {
gu.openConnection(brokenSite, null, null, "GET", true);
}
catch (err) {
console.log('got: ' + err);
}
});
When I run this code I get:
Error: getaddrinfo ENOENT. It is never caught in the try catch
It works for me, when supplying an error handler for the request:
req.on('error', errorHandler);
I see that you also do that, but you set it after issuing
req.end();
Could you try issuing the end() after you attached the error handler?
As a side note, I really recommend request, as it handles issues like this with sensible defaults. It's really a breeze to work with.
Edit: Here is a simple example showing that attaching an error handler lets me handle ENOENT/ENOTFOUND errors:
var http = require('http');
var req = http.request({hostname: 'foo.example.com'}, function(err, res) {
if(err) return console.error(err);
console.log('got response!');
});
req.on('error', function(err) {
console.error('error!', err);
});
Another piece of valuable information: I'm not sure how it fits in with fibers, but in general, you should never throw in nodejs asynchronous code. It rarely works the way you want. Instead, use the standard practice of passing any error as the first parameter to the next callback, and handle the error where it makes sense (usually, high up in the call chain where you can do something sensible with it).
You can scrape the page for the error code.

Categories

Resources