How can I have Node re process /etc/hosts? - node.js

So for unit testing I need to redirect a domain to a new IP for a specific machine. I've setup a route in node to update the machine's hosts file.
exports.hosts = function hosts(req, res) {
var domain = req.params.domain;
var ip = req.params.ip;
if (domain === 'localhost') {
res.json(500, {message: 'invalid domain'});
return;
}
async.waterfall([
function (callback) {
fs.readFile('/etc/hosts', callback);
},
function (data, callback) {
// Remove existing entry
var lines = data.toString().split('\n');
data = '';
for (var line in lines) {
if (!_str.endsWith(lines[line], domain) && lines[line]) {
data += lines[line] + '\n';
}
}
callback(null, data);
},
function (data, callback) {
if (ip) {
data += ip + ' ' + domain + '\n';
}
callback(null, data);
},
function (data, callback) {
fs.writeFile('/etc/hosts', data, callback);
}
],
function (err) {
if (err) {
res.json(500, err);
} else {
res.send(200);
}
});
};
The edit works fine. The issue is that I the next call to the domain from the node process still goes to the last IP address. If I restart Node it sees the new IP address in the hosts file.
How can I get Node to see the updated hosts file without restarting the process?

I know this is late, but I imagine that similar to environment variables, hosts file info may be loaded and cached. By the same token you must restart software for those new env variables to be noticed, you may need to kill the node process and restart it to get the new hosts entry. If you install something like pm2, you would adjust your initial kickoff command slightly: pm2 start app.js instead of node app.js. Then every time you update your hosts file, kill your app and pm2 will restart it. Killing your app is as easy as process.kill(), process.exit(), or throw an Error.

Related

How to get an instance of an existing server in Node.js?

I'd like to get the number of connections of a few servers running on my local machine.
I've successfully used server.getConnections() on a server created via net.createServer(), however I don't know how to use it on an already started server.
I tried obtaining the server instance by connecting to it, using net.connect(). The connection is created successfully and I get a new net.Socket object, however my understanding is that I actually need a net.Server in order to use getConnections().
So my question is, how do I get a net.Server instance of an already running server?
I realize my question is an XY problem, so apologies to all who tried to answer it.
I suspect the answer to the literal question, "how do I get an instance of an existing server", is: "you can't".
I should have added more details to the question, especially what I was trying to achieve.
My application is a load balancer / reverse proxy server. Initially I was able to use getConnections() because I would start the proxy server and a few dummy servers from the same script. However I wanted to make the dummy servers and the proxy separate from each other, so even though I did have complete control over them, I needed to pretend that I didn't actually own the servers.
The solution I found to my specific case, in the end, was to keep a hash list of servers I can connect to (via the reverse proxy), and increment the connection counters every time I connect to a specific server:
let servers = [
{ port: 4000, connectionsCounter: 0 },
{ port: 5000, connectionsCounter: 0 },
{ port: 6000, connectionsCounter: 0 },
];
let myProxyServer = net.createServer((socket) => {
// Open a connection to the first server in the list
net.connect(servers[0].port, () => {
// Once connected, increment the connections counter
socket.on('connect', () => {
servers[0].connectionsCounter++;
});
// When the connection ends, decrement the counter
socket.on('close', () => {
servers[0].connectionsCounter--;
});
});
});
I hope this will be helpful to someone.
If you want to just use the server, you can probably store it as a variable when you call net.createServer()
const my_server = net.createServer();
// do what you want with it
my_server.getConnections();
my_server.listen();
you can make instance of net.createServer() and then get your number of connections from server.on('connection', <callback>):
server.on('connection', (socket) => {
// someone connected
console.log("New active connection");
server.getConnections((err, count) => {
if(err){
console.log(err);
} else {
console.log("Currently " + count + " active connection(s)");
}
});
});
i hope this complete example code help you:
const net = require('net');
const uuid = require('uuid/v1');
const server = net.createServer((socket) => {
socket.uuid = uuid();
socket.on('data', (data) => {
//const response = JSON.parse(data.toString('utf8'));
});
socket.on('error', (err) => {
console.log('A client has left abruptly !');
server.getConnections((err, count) => {
if(err){
console.log(err);
} else {
console.log("Currently " + count + " active connection(s)");
}
});
});
socket.on('end', () => {
console.log("A client has left");
server.getConnections((err, count) => {
if(err){
console.log(err);
} else {
console.log("Currently " + count + " active connection(s)");
}
});
});
});
server.on('error', (err) => {
// handle errors here
console.log("Error:", err);
});
server.on('connection', (socket) => {
// someone connected
console.log("New active connection");
server.getConnections((err, count) => {
if(err){
console.log(err);
} else {
console.log("Currently " + count + " active connection(s)");
}
});
});
// port number.
server.listen(3000, () => {
console.log('opened server on', server.address());
});
or you can use netstat for get number of connection, https://www.npmjs.com/package/node-netstat nodejs module for this solution:
const netstat = require('node-netstat');
myObject = {
protocol: 'tcp',
};
setInterval(function () {
let count = 0;
netstat({
filter: {
local: {port: 3000, address: '192.168.1.1'}
}
}, item => {
// console.log(item);
count++;
console.log(count);
});
}, 1000);
Your application is a bit unclear.
Only the server socket can report how many connections it has. This is why if you create the net.Server you can access that information from it.
If you want to connect to an application and query the number of clients connected to it, the application that you connect to needs to provide that information to you when you ask. This is not information that the socket provides - the application itself has to provide that information.
If you are writing the application that created the net.Server, you can create another net.Server on a different port that you can then connect to and query it for information about the other clients on its other sockets.
If you are trying to generically find the number of connections to a particular application that has a socket, that application needs to be able to tell you, or, as #root mentioned, you need to ask the OS the application is running on. This function will be OS dependent and will likely require elevated privileges. But consider connecting to a socket on a router or IoT device: that application may not be running on any OS at all.

Need to run a NodeJs application from another NodeJs application

I have a NodeJs application running in the following directory
First Application's Path '/users/user1/projects/sampleProject' which is running at 3000 port.
Second Application's Path '/users/user1/demoProjects/demo1' which is going to run at 5000 port on triggering the router function from first application.
The second NodeJs application is not yet started(It will run at port 5000). It need to run independently on hitting a router function in the first NodeJs Application which is running on port 3000 ie(http://localhost:3000/server/startServer). I'm new to NodeJs child processes, Kindly correct me if i'm wrong. And suggest me a right way to do it. Thanks
Start another node application using node.js?
I have tried it like below
// First NodeJs application
import { exec } from "child_process";
router.get('/startServer', async (req, res, next) => {
console.log("Initiated request")
let startServerInstance = 'cd "/users/user1/demoProjects/demo1" && npm run dev'; // path for the second NodeJs application
console.log("Server instance path => " + startServerInstance)
try {
// exec from child process, Spawns a shell then executes the command within that shell
let child = exec(startServerInstance, function (err, stdout, stderr) {
if (err) throw err;
else {
console.log("result ")
res.json({
status: 'success'
});
}
});
} catch (error) {
res.json({
status: 'error',
message: error
});
}
});
The above code executes the command and triggered the second application to run in background but it doesn't return anything. Either error or success result.
You need to use stout and stderror to check other server logs. Also your code is not correct. If you use if without {} it will not go to else statement. That is why you don't see 'result' text in console.
import {
exec
} from "child_process";
router.get('/startServer', async (req, res, next) => {
console.log("Initiated request")
let startServerInstance = 'cd "/users/user1/demoProjects/demo1" && npm run dev'; // path for the second NodeJs application
console.log("Server instance path => " + startServerInstance)
try {
// exec from child process, Spawns a shell then executes the command within that shell
let child = exec(startServerInstance, function(err) {
if (err) throw err;
console.log("Server started");
});
child.stdout.on('data', (data) => {
// this is new server output
console.log(data.toString());
});
child.stderr.on('data', (data) => {
// this is new server error output
console.log(data.toString());
});
res.json({
status: 'success'
});
} catch (error) {
res.json({
status: 'error',
message: error
});
}
});
Child process callback is only called once the process terminates. If the process keeps running, callback is not triggered.
Explained here - https://nodejs.org/docs/latest-v10.x/api/child_process.html#child_process_child_process_exec_command_options_callback

Q: Hot to change Ip in request using tor-request npm

i'm trying to change Ip by using tor
According to Tor-Request Documentation I should be able to do this simply by using
newTorSession
But ip not changing. What is wrong in my code?
var tr = require('tor-request');
requestIP();
tr.setTorAddress('localhost', 9050);
tr.newTorSession( (err) =>
{
console.log (err);
requestIP();
return;
});
//console.log (tr.TorControlPort)
function requestIP() {
tr.request('https://api.ipify.org', function (err, res, body) {
if (!err && res.statusCode == 200) {
console.log("Your public (through Tor) IP is: " + body);
}
})
}
From the doc
You need to enable the Tor ControlPort if you want to programmatically
refresh the Tor session (i.e., get a new proxy IP address) without
restarting your Tor client.
so you need to follow these steps to enable ControlPort then pass that password to tor-request
tr.TorControlPort.password = 'PASSWORD'

Couchbase Server NodeJS SDK Cluster.openbucket Takes 58 Seconds to Open a Connection

I am using NodeJS SDK. In the basic sample that follows I am opening a bucket to insert a single record. I have put each method in a promise to force them run one after another (sequentially) so I can measure each method’s running time.
My OS: Ubuntu 16.04
'use strict';
const couchbase = require('couchbase');
const cluster = new couchbase.Cluster('couchbase://localhost');
const uuid = require('uuid/v4');
console.time('auth');
cluster.authenticate('administrator', 'adminadmin');
console.timeEnd('auth');
function open() {
return new Promise((resolve, reject) => {
console.time('open');
let bucket = cluster.openBucket('test', function (err) {
if (err) {
console.error(err);
reject(err);
}
resolve(bucket);
});
});
}
function insert(bucket, obj) {
return new Promise((resolve, reject) => {
console.time('upsert');
bucket.upsert(`uuid::${blog.name}`, blog, function (err, result) {
if (err) {
console.log(err);
reject(err);
}
resolve(bucket);
});
});
}
function dc(bucket) { // disconnect
return new Promise((resolve, reject) => {
console.time('dc');
bucket.disconnect();
resolve('ok');
});
}
// data to insert
let blog = {
id: uuid(),
name: 'Blog A',
posts: [
{
id: uuid(),
title: 'Post 1',
content: 'lorem ipsum'
}
]
};
open().then((bucket) => {
console.timeEnd('open');
insert(bucket, blog).then((bucket) => {
console.timeEnd('upsert');
dc(bucket).then((res) => {
console.timeEnd('dc');
console.log(res);
});
});
});
The output is:
auth: 0.237ms
open: 58117.771ms <--- this shows the problem
upsert: 57.006ms
dc: 0.149ms
ok
I ran sdk-doctor. It gave me two lines worth mentioning:
“WARN: Your connection string specifies only a single host. You should consider adding additional static nodes from your cluster to this list to improve your applications fault-tolerance”
“INFO: Failed to retreive cluster information (status code: 401)”
and the summary is:
Summary:
[WARN] Your connection string specifies only a single host. You should consider adding additional static nodes from your cluster to this list to improve your applications fault-tolerance
Would anyone please help?
According to this answer in the Couchbase forum, it seemed that my DNS servers were not configured properly.
It looks as though your DNS servers may be configured improperly. As part of the normal bootstrap procedure, we attempt to resolve SRV records for the hostname that is provided, it looks like you’re DNS servers may be timing out when trying to do this, causing a substantial delay when connecting. A quick way to test this theory is to add an additional hostname to your bootstrap list to disqualify the connection string from our DNS-SRV policy (for instance, use: couchbase://localhost,invalidhostname).

nodeJS blocking all requests until it calls back

I've developed a nodeJS API (using express) which allow users to login and get a list of files that they have stored in a remote server. And as you understand, the code must be non-blocking so the webserver can still responds to logging in requests, even if there are some users fetching theirs files lists.
Every time a user make a request to get his files list, the listOfFiles function is called.
This is the code:
exports.listOfFiles = function(req,res){
db.Account.find({where: {id:1}}).then(function(newAcc){
console.log("encontrou a account");
getFiles('/', newAcc.accessToken, '0', newAcc, function(error){
if (error) {
log.error('Error getting files');
}else{
console.log("callback!")
}
});
});
}
getFiles function: this function is responsible for fetching the file list from the remote server, and store them in a postgres database
function getFiles(path, accessToken, parentID, newAcc, callback){
var client = new ExternalAPI.Client({
key: config.get("default:clientId"),
secret: config.get("default:clientSecret")
});
client._oauth._token = accessToken;
var options = {
removed : false,
deleted : false,
readDir: true
}
//this is the instruction that fetch an array of items
//(metadata only) from a remote server
client.stat(path, options, function(error, entries) {
if (error) {
if (error.status == 429) {
console.log(accessToken + 'timeout')
setTimeout(
getFiles(path, accessToken, parentID, callback),
60000);
}else{
log.error(error);
callback(error,null);
}
}
else {
//When the array os items arrives:
console.log("RECEIVED FILES")
var inserted = 0;
var items = entries._json.contents;
for(var file in items){
var skyItemID = uuid.v1();
var name = items[file].path.split('/').pop();
var itemType;
if (items[file].is_dir) {
itemType = 'folder';
}else{
itemType = 'file';
}
newAcc.createItem({
name : name,
lastModified: items[file].modified,
skyItemID: skyItemID,
parentID: parentID,
itemSize: items[file].bytes,
itemType : itemType,
readOnly: items[file].read_only,
mimeType: items[file].mime_type
}).then(function(item){
console.log(item.name)
if (++inserted == items.length) {
console.log(inserted)
console.log(items.length)
console.log("callsback")
callback();
}
}).catch(function(error){
log.error('[DROPBOX] - Filename with special characters');
callback(new Error);
return;
});
}
}
});
}
The problem here is, the moment that webserver prints console.log("RECEIVED FILES") in our console, it stops responding to all other requests, such as log in or fetch files requests from other users.
And it starts responding again when it prints console.log("callback!"). So, i'm assuming that somehow nodeJS is blocking itself until getFiles function is finished and called back.
I think that this is not a normal behaviour. Shouldn't nodeJS be responding to responds to other requests even if there are some operations running in background? Shouldn't getFiles function being run in background and not affecting/blocking all other requests? What am I doing wrong?
Thanks!
I am facing the same kind of problem for long time server http request blocks the service for response other client requests. This is my topic. What is the correct behavior for Node.js while Node.js is requesting a long time http request for other servers Currently, I got no answer for that. If you got the answer, please reply me. Thanks.

Resources