Tag Archives: nodejs

curl_openssl_4_not_found

Dynamic Linking Error: /usr/lib/x86_64-linux-gnu/libcurl.so.4: version `CURL_OPENSSL_4′ not found

  1. Why is this happening?
  2. Am I in the same situation?
  3. The Million $ Solution

Why is this happening?

Well, if you end up on this page, you for sure are in a bad situation.

It took me some good hours to debug and solve this problem but maybe you can close this chapter much faster. You are encountering this issue because a native module that you are using depends on CURL_OPENSSL_4.

Am I in the same situation?

There are multiple reasons why you may encounter this error: CURL_OPENSSL_4 not found.

The most common ones are:

  1. Symbolic Link from /usr/lib/x86_64-linux-gnu/libcurl.so.4 -> /usr/lib/x86_64-linux-gnu/libcurl.so.4.X.X is bad. You might need to recreate it.
  2. libcurl version is not installed -> Easy fix -> install it
  3. libcurl version is wrong -> This is what we’re gonna cover

If you are a Linux user who is also into system level software development, you may find yourself in situations where-in you need information related to symbols in an object file. You’ll be glad to know there exists a command line utility – nm – that you can use in these situations.

The nm command line utility basically lists symbols from object files. Here’s the tool’s syntax:

nm [OPTIONS] OBJECT-FILENAME

Run:

nm -D /usr/lib/x86_64-linux-gnu/libcurl.so.4|grep CURL

What you should see is:

0000000000000000 A CURL_OPENSSL_4

What you might see:

0000000000000000 A CURL_OPENSSL_3

Well clearly things don’t look good. Your Linux distribution is built using other libcurl version. You may attempt to uninstall it and add another version but it might break apt.

The Million $ Solution

I switched to a Linux distribution that includes libcurl4.

I was using node-12-slim which is built on Debian-Stretch. You cannot install libcurl4 on this version since it’s built on CURL_OPENSSL_3.

I switched to node-12-buster-slim which is built on top of Debian-Buster and installed libcurl4 and things started working.

apt-get install libcurl4 -y

That’s all 🙂

primary-node

Primary node election in distributed computing

Primary node can help with coordination of multiple node deployed in a cloud. One of the projects I’ve worked on had a NodeJS worker that ran multiple types of tasks. I wanted to upgrade this setup in order to be easily scalable, have a primary node (or coordinator) that triggers the tasks and continue processing even when some of the nodes fail.

The Checklist

  • All nodes may participate in an “election” to choose the coordinator
  • Support any number of nodes, including 1 node setup
  • Handle node fail (even the coordinator node) without impacting the flow
  • Allow new nodes to join the party
  • Don’t depend on an expensive technology (paid or resource hungry)

Besides the main scope of the solution I also needed to ensure that the election of the coordinator follows these 3 basic principles:

  • Termination: the election process must complete in a finite time
  • Uniqueness: only one node can be coordinator
  • Agreement: all other nodes know who’s the coordinator.

After I established that I have all the scenarios in mind, I started investigating different algorithms and solutions that the market uses (Apache Zookeeper, Port Locking, Ring Networks). However, most of these require a lot of setup or were incompatible in a multi server setup and I also wanted to embrace a KISS approach so continue reading to see the solution.

The Primary Node Election Algorithm

  1. Node generates a random numeric id
  2. Node retrieves a COORDINATOR_ID key from Redis
  3. If key !NULL
    • We have a coordinator
    • Wait Z minutes (e.g. Z = 1 hour)
    • GoTo Step2
  4. If key NULL
    • No coordinator announce
    • Push the id from Step1 in a Redis list
    • Waits X seconds (depending on how long the deployment takes, e.g. 10 seconds)
    • Retrieve all items in the list and extract the highest number
    • If result === node id
      • Current node is primary
      • Set Redis key COORDINATOR_ID with expiry Z+X
      • Do all the hard work 🙂
    • Wait Z minutes
    • GoTo Step2

Downside of this solution is that if the coordinator node fails, it actually takes 2*Z until a new election takes place.

There’s room for improvement so please don’t hesitate to leave a feedback 🙂

OSX Global NPM Module command not found

In case you ended up in a situation where you just installed a global NPM module, but it still throws command not found, here’s what you have to do:

Find out where the global NPM modules are installed by running:

npm prefix -g

Double check that your $PATH does not already contain that value:

echo $PATH

If the value is not included, you must update your etc/paths with the NPM location:

sudo vi /etc/paths

Add the value returned by npm prefix -g preceded by /bin

e.g. /Users/catalinmunteanu/.npm-global/bin

Save the file and exit.

Open a new terminal tab/window and retry the command.

Cheers!

Node n permission denied without sudo

Each time I do a fresh install of the Node Version Management tj/n I end up getting the permission denied when running npm install.

If you also ran into this issue, well, there’s a quick fix.

The issue is caused by the Node Version Management for which the owner is the root.

The two following steps will help you continue in peace 😀

which n

Returns the install location of the Node Version Management package. e.g. /Users/username/n

sudo chown -R $(whoami) <PATH_WHICH_N>

Sets the current user as owner.

You can now install the NPM packages without the power of sudo.

NPM module command not found

Until you properly config your environment you’ll probably run into the command not found error when trying to run globally installed NPM modules.

Solution for Linux and OSX:

Step 1 – check if the path is correct

You need to have /users/<ME>/.npm-global/bin in your $PATH

echo $PATH

If the printed string doesn’t contain the above path, continue to Step 2

Step 2 – add npm global install path

We need to adjust the $PATH in order to contain the path to the NPM global module folder:

export PATH=$PATH:~/.npm-global/bin

Step 3 – reload .bashrc

The .bashrc file is usually only reloaded on startup. Run the bellow command to reload it again after you made the changes from Step 2.

source ~/.bash_profile

That’s all. Your global NPM modules should now work in your terminal.

Socket.IO AngularJS Wrapper

I’ve been playing around with Socket.IO and AngularJS. To make things easier I created this service which can be used for transferring data between the client (which could be a web page) and a NodeJS server.

The app is served by NodeJS so the Socket.IO server is listening on same location.

'use strict';

angular
.module('APP')
.factory('$WS', function($rootScope) {
    var self = this;

    self.ready = false;

    self.socket = io.connect(location.host, {
        'connect timeout':       100,
        'reconnection delay':    100
    });

    self.socket.on('init', function() {
        console.log('init');
    });

    self.socket.on('disconnect', function() {
        console.log('socket disconnected');
    });

    self.socket.on('connect', function() {
        console.log('socket connected');
    });

    return {
        ready: function(callback) {
            if(self.ready) {
                callback();
                return;
            }

            self.socket.on('connect', function() {
                $rootScope.$apply(function() {
                    self.ready = true;
                    callback.apply(self.socket);
                });
            });
        },
        on: function(eventName, callback) {
            self.socket.on(eventName, function() {
                var args = arguments;

                $rootScope.$apply(function() {
                    callback.apply(self.socket, args);
                });
            });
        },
        emit: function(eventName, data, callback) {
            self.socket.emit(eventName, data, function() {
                var args = arguments;
                $rootScope.$apply(function() {
                    if(callback) {
                        callback.apply(self.socket, args);
                    }
                });
            });
        }
    };
});

Usage:

angular
.module('APP')
.controller('TestController', ['$scope', '$WS', function($scope, $WS) {

    $scope.messages = [];

    // Connect websocket
    $WS.ready(function() {
    
        // Receive message
        $WS.on('chat/message', function(data) {
            
            // Validate input data
            if(data.message_id) {
                console.log(data);
                $scope.messages.push(data);
            }
        });
    });

    // You can add another ready state listener for the same connection
    // Let's consider we have a method which sends messages
    $scope.send_message = function(msg_title, msg_value) {
        
        $WS.ready(function() {
            // Emit message
            $WS.emit('chat/message', {
                title:    msg_title,
                message:  mgs_value
            });
        });
    };

}]);

 

This is just basic usage.  Will be back with NodeJS & Socket.IO server example.

NodeJS AES256 Encryption/Decryption

In one of my projects I needed to encrypt some data. I decided to use AES256 symmetrical encryption algorithm.

So this is what I’ve come to (aes_encryption.js):

var crypto	= require('crypto'),
    cipher_seed = 'some_random_characters';
 
var encrypt = function(text) {
	var cipher	= crypto.createCipher('aes-256-cbc', cipher_seed),
	    crypted	= cipher.update(text, 'utf8', 'hex');

	crypted += cipher.final('hex');

	return crypted;
};
 
var decrypt = function(text) {
	var decipher  = crypto.createDecipher('aes-256-cbc', cipher_seed),
	    decrypted = decipher.update(text, 'hex', 'utf8');

	decrypted += decipher.final('utf8');

	return decrypted;
};
 
module.exports.encrypt = encrypt;
module.exports.decrypt = decrypt;

Usage:

var AES = require('path_to_aes_encryption.js');

var data = {
    name:    'Catalin',
    surname: 'Munteanu',
    address: 'Romania'
};

// Encryption
var encrypted_data = AES.encrypt(JSON.stringify(data));

// Decryption
var decrypted_data = JSON.parse(AES.decrypt(encrypted_data));

Don’t forget that if the cipher seed is changed or lost all the encrypted data is also lost.

Easy, right?

 

 

Finalize – JavaScript Asynchronous Requests Queue

Most web apps send lots of asynchronous http requests. Sometimes you need to know when some selected requests are finished so that you can pass to the next step.

The following function can be used for creating a queue with asynchronous requests using JavaScript and be notified when the queue is empty again (all selected requests are finished):

function Finalize(_callback) {
	var count = 0,
	    exec  = false;

	if((typeof _callback !== 'undefined') && (_callback !== null)) {
		this.exec = function() {
			exec = true;
			if(count === 0) {
				_callback();
			}
		}
		this.queue = function() {
			count++;
			return function() {
				count--;
				if(exec && (count === 0)) {
					_callback();
				}
			}
		}
	} else {
		this.exec  = function() {};
		this.queue = function() {};
	}
}

Usage:

var request_set = new Finalize(function() {
    // Code inside this function will be executed at the end
});

// To add an item to the queue
var first_item = request_set.queue();

// Let's add another item
var second_item = request_set.queue();

// The code inside the final callback will only be called after
// all the items in queue are completed.
// Let's consider we have two async requests:
jQuery.get('http://example.com', function(data) {
    // We now have the response from the first request
    // Remove one item from queue by calling the item's name
    first_item();
});

// The items can also be removed by passing them directly as callback
jQuery.get('http://example.com', second_item);

// You can even skip declaring items and create them on the fly as the callback function
jQuery.get('http://example.com', request_set.queue());

// After you've added all items to the queue we need to execute it
request_set.exec();

The function can also be used in NodeJS.