Nikola Brežnjak blog - Tackling software development with a dose of humor
  • Home
  • Daily Thoughts
  • Ionic
  • Stack Overflow
  • Books
  • About me
Home
Daily Thoughts
Ionic
Stack Overflow
Books
About me
  • Home
  • Daily Thoughts
  • Ionic
  • Stack Overflow
  • Books
  • About me
Nikola Brežnjak blog - Tackling software development with a dose of humor
CodeProject, NodeJS

Deploying MongoDB and Node.js application on OpenShift

This is a post about getting started with OpenShift Online on a Windows machine by deploying a MongoDB, Node.js and RockMongo application for free. The reason why this wasn’t a title is that it’s just too darn long :). Cool, with getting that off my chest, we can now start…

OpenShift Online – Red Hat’s public cloud application development and hosting platform that automates the provisioning, management and scaling of applications so that you can focus on writing the code for your business, startup, or next big idea.

If you’ve tried OpenShift, you may have come across this offical how-to video only to find it completely useless. The accompanying official blog post is way better but still lacks some exact example code on, for example, how to connect to MongoDB from Node.js. Read on to see how I did it.

First, you have to create a new OpenShift account in case you don’t have one already.

Once you login to the site you get a nice looking dashboard and in order to create a new application you could click on the Add application button:
openshift_login

which would then offer really a lot of options:
openshift_applist

Setting up WordPress is easy as clicking the WordPress icon and naming your app on the next page:
openshift_wp
and clicking the Create Application button. After the process finishes (few mins) you get the instructions on how to alter the application:
openshift_wp_done
Basically, you clone the application’s source code with git and after doing some changes you push them back. At this point, all you have to do is visit the link of your newly created application (you can see the link in your Applications tab in the OpenShift admin interface) and you’ll get the WordPress init install screen:
openshift_wp_isntall

If you ever installed WordPress before everything should be familiar from now on. And there you have it – you have WordPress installed in a matter of few clicks.

Keep calm and roll up your sleves

You may be wondering where’s the MongoDB and Node.js from the title? Hack on…

So, we saw how easy it was to create an app from web admin interface, but since we’re devs and we loove terminal (don’t we ;)) we’re gonna take a different route here. OpenShift offers the OpenShift Client tools aka rhc. In order to install rhc you first have to have Ruby installed, and the easiest way to do this on a Windows machine is to install the RubyInstaller:

openshift_rubyinstaller

Just click the big red download button and I’m sure you now how to take it from there. Important note though, while installing just make sure that you check the Add Ruby executables to your PATH option:
openshift_rubypath

After the installation is done you can fire up your terminal (I use Console 2, and you can see my settings here: Customize Console 2 on Windows machine) and run

gem install rhc

and once this is done just run rhc setup  (this is an important part for us Windows users, as the official documentation on Installing OpenShift RHC Client Tools says we should only run rhc , and that does not work – as noted by the comments on that post).

Now we can use rhc to create a new application. To create a new application named myTest with Node.js and MongoDB you have to run:

rhc app create myTest nodejs-0.10 mongodb-2.4

and you’ll get an output similar to this:

C:\Users\Nikola\Desktop>rhc app create myTest nodejs-0.10 mongodb-2.4
DL is deprecated, please use Fiddle
Application Options
-------------------
Domain:     chavo
Cartridges: nodejs-0.10, mongodb-2.4
Gear Size:  default
Scaling:    no

Creating application 'myTest' ... done

  MongoDB 2.4 database added.  Please make note of these credentials:

   Root User:     admin
   Root Password: ..bip..Bip..
   Database Name: mytest

Connection URL: mongodb://$OPENSHIFT_MONGODB_DB_HOST:$OPENSHIFT_MONGODB_DB_PORT/

Waiting for your DNS name to be available ... done

Cloning into 'mytest'...
The authenticity of host 'mytest-chavo.rhcloud.com (54.235.21.98)' can't be established.
RSA key fingerprint is cf:ee:77:cb:0e:fc:02:d7:72:7e:ae:80:c0:90:88:a7.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'mytest-chavo.rhcloud.com,54.235.21.98' (RSA) to the list of known hosts.
Enter passphrase for key '/c/Users/Nikola/.ssh/id_rsa':
remote: Counting objects: 21, done.
remote: Compressing objects: 100% (17/17), done.
Receiving objects: 100% (21/21), 20.22 KiB, done.ceiving objects:  90% (19/21)

Your application 'mytest' is now available.

  URL:        http://mytest-chavo.rhcloud.com/
  SSH to:     [email protected]
  Git remote: ssh://[email protected]/~/git/mytest.git/
  Cloned to:  C:/Users/Nikola/Desktop/mytest

Run 'rhc show-app myTest' for more details about your app.

If you’re concerned about that ‘DL is deprecated, please use Fiddle‘, don’t be as it’s a mere warning as they say on Stackoverflow (or if you want to explore this topic further make sure you check this question on SO).

If you get an error saying that there’s no such cartridge you will get a list of all the available cartridges which you can use, so just adjust the above command accordingly

C:\Users\Nikola\Desktop>rhc app create
DL is deprecated, please use Fiddle
When creating an application, you must provide a name and a cartridge from the
list below:

Short Name      Full name
==========      =========
diy-0.1         Do-It-Yourself 0.1
jbossas-7       JBoss Application Server 7
jbosseap-6      JBoss Enterprise Application Platform 6
jenkins-1       Jenkins Server
nodejs-0.10     Node.js 0.10
nodejs-0.6      Node.js 0.6
perl-5.10       Perl 5.10
php-5.3         PHP 5.3
zend-5.6        PHP 5.3 with Zend Server 5.6
php-5.4         PHP 5.4
zend-6.1        PHP 5.4 with Zend Server 6.1
python-2.6      Python 2.6
python-2.7      Python 2.7
python-3.3      Python 3.3
ruby-1.8        Ruby 1.8
ruby-1.9        Ruby 1.9
jbossews-1.0    Tomcat 6 (JBoss EWS 1.0)
jbossews-2.0    Tomcat 7 (JBoss EWS 2.0)
jboss-vertx-2.1 Vert.x 2.1

Please specify the name of the application and the web cartridge to install
Usage: rhc app-create <name> <cartridge> [... <cartridge>] [... VARIABLE=VALUE]
[-n namespace]
Pass '--help' to see the full list of options

Keep on rockin’ on

MongoDB is an open-source document database, and the leading NoSQL database. In order to add RockMongo MongoDB administration, which is a web front-end for interacting with your MongoDB, you have to execute this command:

rhc cartridge add rockmongo

after which you get an output similar to this:

C:\Users\Nikola\Desktop\mytest>rhc cartridge add rockmongo
DL is deprecated, please use Fiddle
Using rockmongo-1.1 (RockMongo 1.1) for 'rockmongo'
Adding rockmongo-1.1 to application 'mytest' ... done

rockmongo-1.1 (RockMongo 1.1)
-----------------------------
  Gears:          Located with mongodb-2.4, nodejs-0.10
  Connection URL: https://mytest-chavo.rhcloud.com/rockmongo/

Please make note of these MongoDB credentials:
  RockMongo User: admin
  RockMongo Password: ..i.aint.telin'..
URL: https://mytest-chavo.rhcloud.com/rockmongo/

If you login to RockMongo by using the username and pass provided you will get a simple but useful interface:
openshift_rockmongo

However, if you prefer to do it via shell, you can do this:

rhc ssh

and after that start interactive command-line interface by typing mongo :

[mytest-chavo.rhcloud.com 532812f94382eca22b000657]\> mongo
MongoDB shell version: 2.4.6
connecting to: 127.9.197.130:27017/admin
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
        http://docs.mongodb.org/
Questions? Try the support group
        http://groups.google.com/group/mongodb-user

Now let’s select a database, which will be same as your app’s name.

> use mytest
switched to db mytest

To insert some record we can do something like this:

> var a = {"user":"nikola", points:10};
> db.scores.insert(a);

and check if it was successfully inserted:

> db.scores.find();
{ "_id" : ObjectId("53284189d6e5e4aedb1fbafd"), "user" : "nikola", "points" : 10 }

To query this information with Node.js you first have to install mongojs with npm install mongojs . Then open up the server.js  file (it is in the root folder of your application) and add these lines in the self.createRoutes  object:

self.routes['/db'] = function(req, res) {
    var mongojs = require('mongojs');
    var dbName = "/mytest";
    var connection_string = process.env.OPENSHIFT_MONGODB_DB_USERNAME + ":" +  process.env.OPENSHIFT_MONGODB_DB_PASSWORD + "@" + process.env.OPENSHIFT_MONGODB_DB_HOST + dbName;
    var db = mongojs(connection_string, ['scores']);
    var books = db.collection('scores');

    db.scores.find(function(err, docs) {
       res.send(docs); 
    });
};

All aboard, and ready to take-off

Now it’s time to add the changes to the staging state with git add . (you may wanna check Git if this looks daunting). You can check the status of the files with git status . To commit the changes you have to execute:  git commit -a -m “Added code to talk to db” and finally git push  to send the changes to OpenShift for deployment.

Now, if you followed this tutorial, on the link http://mytest-chavo.rhcloud.com/db (notice this db here, and ofc exact link would reflect to your app) you should get this output:

openshift_dboutput

And a quick closing with with one useful command to get the overview of the app settings:

C:\Users\Nikola\Desktop\mytest>rhc app show
DL is deprecated, please use Fiddle
mytest @ http://mytest-chavo.rhcloud.com/ (uuid: 532812f94382eca22b000657)
--------------------------------------------------------------------------
  Domain:     chavo
  Created:    10:33 AM
  Gears:      1 (defaults to small)
  Git URL:    ssh://[email protected]/~/git/mytest.git/
  SSH:        [email protected]
  Deployment: auto (on git push)

  mongodb-2.4 (MongoDB 2.4)
  -------------------------
    Gears:          Located with nodejs-0.10, rockmongo-1.1
    Connection URL: mongodb://$OPENSHIFT_MONGODB_DB_HOST:$OPENSHIFT_MONGODB_DB_PORT/
    Database Name:  mytest
    Password:       ..ccc...
    Username:       admin

  nodejs-0.10 (Node.js 0.10)
  --------------------------
    Gears: Located with mongodb-2.4, rockmongo-1.1

  rockmongo-1.1 (RockMongo 1.1)
  -----------------------------
    Gears:          Located with mongodb-2.4, nodejs-0.10
    Connection URL: https://mytest-chavo.rhcloud.com/rockmongo/

And this is it, now it’s your time to make something useful with it!

CodeProject, NodeJS

Getting started with Nodejitsu on Windows by deploying a MEN framework

Disclaimer: I’m in no way affiliated with Nodejitsu or any of the frameworks that I listed below in the post. I’m just documenting my experience with them – problems (and solutions) I’ve faced while trying these new technologies on a Windows machine.

MEN – MongoDB, Express, Node.js, and if you think MEN is not mean enough, take a look at the post on Deploying MEAN.io to Nodejitsu from Windows machine.

Nodejitsu is a cloud platform as a service based on Node.js and serves Node.js applications on their platform. Signup is free, you don’t have to enter billing info in order to try 2 months free (yes, databases work too!), just click on the “Do not select a product now” button:
nodejitsuFreeSignup
After signing up you get a confirmation mail like this:

Welcome to Nodejitsu!
Your Nodejitsu account is activated and ready to go!
username: userName
To confirm your account, install the latest jitsu:
sudo npm install jitsu -g
and then run:
jitsu users confirm userName big-h@5h
This will allow you to deploy applications with:
jitsu deploy

Setting up databases in the web admin interface is easy as you only have to literally click one button after deciding which database type and provider you want:
nodejitsuDatabases

Hackaton starters are gaining momentum  and there are quite a few of them already like:

  • Hackaton starter
  • Drywall
  • DozerJS
  • Skeleton
  • MEAN – only one which offers Angular out of the box (a follow up post on this is here)

I decided to try out Skeleton, mainly because I liked the “just right” Goldilocks reference 🙂

So, as the site suggests, you first have to installnodemon , gulp  andmocha , then clone the github repo, npm & bower install everything and you’re done:

# Install global dependencies
npm install -g nodemon gulp mocha

# Clone the repoo (and fetch only the latest commits)
git clone --depth=1 [email protected]:dstroot/skeleton.git
cd skeleton

# Install local dependencies
npm install
bower install

# Start everything up with Gulp 
# (builds the assets and starts the app with nodemon)
gulp

Everything works for you? Great! For the rest of unlucky ones, you may got (like me) after running gulp :

gulp

module.js:340
    throw err;
          ^
Error: Cannot find module 'jshint-stylish'
    at Function.Module._resolveFilename (module.js:338:15)
    at Function.Module._load (module.js:280:25)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object.<anonymous> (C:\Users\Nikola\Desktop\skeleton\gulpfile.js:22:21)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)

I tried npm install jshint-stylish , and ran gulp again:

C:\Users\Nikola\Desktop\skeleton>gulp
[gulp] Using gulpfile C:\Users\Nikola\Desktop\skeleton\gulpfile.js
[gulp] Starting 'clean'...
[gulp] Finished 'clean' after 11 ms
[gulp] Starting 'styles'...
[gulp] Starting 'scripts'...
[gulp] Starting 'images'...
[gulp] Finished 'images' after 2.75 ms
[gulp] Starting 'lint'...
[gulp] Finished 'lint' after 192 ms
[gulp] Starting 'watch'...
[gulp] Finished 'watch' after 151 ms
[gulp] Starting 'develop'...
[gulp] Finished 'develop' after 1.68 ms
[gulp] Live reload server listening on: 35729
[gulp] gulp-notify: [Gulp notification] Clean task complete

events.js:72
        throw er; // Unhandled 'error' event
              ^
Error: Incorrect OS. node-notify requires Mac OS 10.8 or higher
    at C:\Users\Nikola\Desktop\skeleton\node_modules\gulp-notify\node_modules\no
de-notifier\lib\terminal-notifier.js:46:25
    at Object.module.exports.isMacOSX (C:\Users\Nikola\Desktop\skeleton\node_mod
ules\gulp-notify\node_modules\node-notifier\lib\utils.js:24:12)
    at Notifier.notify (C:\Users\Nikola\Desktop\skeleton\node_modules\gulp-notif
y\node_modules\node-notifier\lib\terminal-notifier.js:44:11)
    at module.exports (C:\Users\Nikola\Desktop\skeleton\node_modules\gulp-notify
\lib\report.js:17:5)
    at Transform._flush (C:\Users\Nikola\Desktop\skeleton\node_modules\gulp-noti
fy\lib\notify.js:41:5)
    at Transform.<anonymous> (C:\Users\Nikola\Desktop\skeleton\node_modules\gulp
-notify\node_modules\through2\node_modules\readable-stream\lib\_stream_transform
.js:130:12)
    at Transform.g (events.js:180:16)
    at Transform.EventEmitter.emit (events.js:92:17)
    at finishMaybe (C:\Users\Nikola\Desktop\skeleton\node_modules\gulp-notify\no
de_modules\through2\node_modules\readable-stream\lib\_stream_writable.js:363:12)

    at endWritable (C:\Users\Nikola\Desktop\skeleton\node_modules\gulp-notify\no
de_modules\through2\node_modules\readable-stream\lib\_stream_writable.js:370:3)

As the message says (note also on their website),  gulp notify , which uses node-notify  is not supported on Windows. The way I solved this was that I removed all of the .pipe(notify({ onLast: true, message: ‘Scripts task complete’ }))  lines from gulpfile.js, but it still wasn’t enough! Running lint job made the gulp fail, so I removed that to and woila then it all worked.

A note (though you can look this up on the official github page also) on how to setup Google login by:

  • Visit Google Cloud Console
  • Click CREATE PROJECT button
  • Enter Project Name, then click CREATE
  • Then select APIs & auth from the sidebar and click on Credentials tab
  • Click CREATE NEW CLIENT ID button
    • Application Type: Web Application
    • Authorized Javascript origins: http://localhost:3000
    • Authorized redirect URI: http://localhost:3000/auth/google/callback
  • Copy and paste Client ID and Client secret keys into config/config.js

:exclamation:Note: When you ready to deploy to production don’t forget to add your new url to Authorized Javascript origins and Authorized redirect URI, e.g. http://my-awesome-app.nodejitsu.com and http://my-awesome-app.nodejitsu.com/auth/google/callback respectively. The same goes for other providers.

Deploying to Nodejitsu is done by firstly  loging in and then executing jitsu deploy:

C:\Users\Nikola\Desktop\skeleton>jitsu login
info:    Welcome to Nodejitsu hitman666
info:    jitsu v0.13.15, node v0.10.26
info:    It worked if it ends with Nodejitsu ok
info:    Executing command login
prompt: username:  (hitman666)
prompt: password:
info:    Authenticated as hitman666
info:    Nodejitsu ok

C:\Users\Nikola\Desktop\skeleton>jitsu deploy

Boom, your app is live on Nodejitsu server and it should look like this (ofc YMMV in term of link):
skeletonWelcomeScreen

NodeJS

Can’t install gulp.js or update npm past version 1.2.32

My problem started with not being able to install gulp. I checked my npm version (npm –version ) and saw I have version 1.2.32 whilst the time of this writing the newest version was 1.4.3. After countless trying of commands like

npm cache clean
npm update -g npm
npm update
npm install gulp -g

and reinstalling Node.js from official site I realized that even though I removed my Node.js installation from C:\Program Files\nodejs  I still had it in C:\Program Files (x86). Doh! :/ So, after I removed both installations, I redownloaded the exe file from Nodejs.org and installed to C:\nodejs. After this, when I ran npm install gulp everything went well. However, when I tried to install it globally (npm install gulp -g ) I got:

npm ERR! peerinvalid The package generator-karma does not satisfy its siblings' peerDependencies requirements!
npm ERR! peerinvalid Peer [email protected] wants generator-karma@~0.6.0
npm ERR! peerinvalid Peer [email protected] wants generator-karma@>=0.6.0

npm ERR! System Windows_NT 6.1.7601
npm ERR! command "C:\\nodejs\\\\node.exe" "C:\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install" "gulp-util" "-g"
npm ERR! cwd C:\Users\Nikola\Desktop\skeleton
npm ERR! node -v v0.10.26
npm ERR! npm -v 1.4.3
npm ERR! code EPEERINVALID
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR!     C:\Users\Nikola\Desktop\skeleton\npm-debug.log
npm ERR! not ok code 0

Then I uninstalled npm uninstall -g generator-karma and npm uninstall -g generator-angular , and gulp installed fine.

 

Heroku, NodeJS, Windows

Getting Started with Node.js on Heroku on a Windows machine

Heroku is a cloud platform as a service supporting several programming languages which lets app developers spend their time on their application code, not managing servers, deployment, ongoing operations, or scaling…

If you tried to get your feet wet with Heroku by deploying Node.js application, you must have come across this article on Heroku’s documentation (and you also may have run into problems when starting Foreman if you’re on a Windows machine – read onward to see how I’ve solved it).

Obviously, first you have to make an account on Heroku, then install Heroku toolbelt (it gives you git, foreman, and heroku command line interface) for your environment (in my case Windows):
herokuToolbelt

Fire up your command prompt (I use Console2) and run heroku login . You need to have Node.js installed (in case you don’t you can download it here).

Write some Node.js app and put it in app.js file:

//app.js
var express = require("express");
var app = express();

app.get('/', function(req, res) {
  res.send('Every day in every way I\'m serving more requests');
});

var port = Number(process.env.PORT || 5000);
app.listen(port, function() {
  console.log("Listening on " + port);
});

If you have  package.json  file then Heroku will recognize your app as Node.js app. In order to create it, run npm init  in the root directory of your app. The npm init utility will walk you through creating a package.json file by asking few questions. If you already made your repository on GitHub and cloned it locally then npm init command in this folder will recognize that too and add:

"repository": {
    "type": "git",
    "url": "https://github.com/yourUsername/appName.git"
}

If you wish, you can freely clone my test app from Github: https://github.com/Hitman666/herokuTestApp.git

Next, install dependencies from your code (in app.js  example the required module is express). Use npm install <pkg> –save  to install a package and save it as a dependency in the package.json file. In my example that would be one command:

npm install express --save

 

You have to set a Procfile, which is a text file in the root directory of your application, to explicitly declare what command should be executed to start a web dyno. In our case this would be the contents of Procfile:

web: node app.js

Now you should be able to start your application locally using Foreman (installed as part of the Heroku Toolbelt) by running foreman start .

But here the party started :/

In my case foreman didn’t start at all, and after a lot of searching, I managed to solve it in few steps. First, I updated my Ruby installation:

gem update --system --source http://rubygems.org/

Then, according to this StackOverflow post I installed former version of foreman:

gem uninstall foreman
gem install foreman -v 0.61

Finally, I added Ruby’s bin folder (Ruby which, in my case, is in C:\Program Files (x86)\Heroku\ruby-1.9.2\bin) to my PATH variable.

Ok, almost there! Lets add our app to git (you should skip the git init command if you already cloned your app from GitHub):

git init
git add .
git commit -m "init"

and finally, lets deploy it to Heroku:

heroku create
git push heroku master

To open the app in your browser run heroku open . To push the changes to GitHub you have to execute git push origin master.

*Now that your app is up and running on heroku (my link) you may want to prevent it from going to sleep mode. Some suggestions on how to achieve this are in this post on StackOverflow (I went with UptimeRobot).

**At some point, as I was fiddling with the apps on Heroku’s website, I deleted all apps and then the git push heroku master  command from my console was not working anymore, so I had to do:

git remote rm heroku
heroku create
git push heroku master

***Also, I wanted to rename my app and that can be done easily:

heroku apps:rename NEWNAME

 

NodeJS, Quick tips

How to use nodemon

Nodemon is a utility that will monitor for any changes in your source and automatically restart your server. Perfect for development. Install it using npm.

npm install -g nodemon

Once installed, instead of node app.js  use nodemon app.js . It will save you a lot of time in the long run, because you won’t need to manually restart the server each time you make a change.

edit: These days I’m using a ever so slightly more popular PM2.

CodeSchool, NodeJS

How to get started with Node.js

Recently I started using CodeSchool to explore new languages/technologies in the web world, and I will post every Tuesday something new that I learn. So far, all I have for them is pure praise, so if you fancy learning something new go check them out. I like them because of one thing in how they do their presentations: first you watch a video in which they explain the concept and then, more importantly (at least in my case), you get the set of challenges where you yourself have to write the code in order to pass on to the next level – awesome! So I would say that their slogan “Learn by doing” is right on the spot.

This is by no means meant as a tutorial, but merely as my notebook where I write down things which I’ve learned. Ok, without further to do, lets check out what’s all this mumbo jumbo buzzword about Node.js.

Node.js (by Ryan Dahl) is in fact a wrapper, written in C, around V8 JavaScript runtime of Google Chrome engine which can be executed on the server.

Blocking vs non-blocking code: Node.js makes non-blocking possible by providing us with a callback function when the process (for example: file reading) is done.

var http = require("http");
var fs = require("fs");

http.createServer(function(request, response){
    response.writeHead(200);
    fs.readFile("file.txt", function(err, contents){
        response.write(contents);
        response.end();
    });
    response.write("This will most likely be printed before the file contents");
}).listen(8080);

To view this, visit http://localhost:8080  in your browser or do a curl request. Interesting thing to note though is that you will not get the same effect if you run it via curl in terminal and in browser, and here is my question on StackOverflow which helps answer why. Long story short (with more info about it later in the post):

…this is simply due to the behavior of the browser rendering engine which cashes the contents until response.end(); arrives, and then renders whole response. Socket.IO and this article should be of help

As explained in the StackOverflow post, I solved this by using Socket.IO (explained in more detail below in the post) and here is the simple example:

//timeoutTest.js
var express = require('express'),
    app = express(),
    server = require('http').createServer(app),
    io = require('socket.io').listen(server);

server.listen(8080);

app.use(express.static(__dirname + '/'));

app.get('/', function (req, res) {
   res.sendfile(__dirname + '/timeoutTest.html');
});

io.sockets.on('connection', function (client) {
   client.emit('msg', "This prints right now on connection.");

   setTimeout(function(){
      client.emit('msg', "This prints out after 3 secs.");      
   }, 3000);
});

//timeoutTest.html
<!DOCTYPE html>
<html>
<head>
    <script src="/socket.io/socket.io.js"></script>
    <script src="jquery.js"></script>
    <script>
    $(document).ready(function(){
        var server = io.connect('http://localhost');
        server.on('msg', function(data){
            $('body').append(data + "<br/>");
        });
    });
    </script>
</head>
<body>
</body>
</html>

Upon first execution of the code Node registers events and then it goes into the so called “event loop”.

Instead of response.write(string)  as the last command, you can put it in end() function like this response.end (string);

How to use event emmiters:

var EventEmitter = require('events').EventEmitter;

var logger = new EventEmitter();

logger.on('error', function (msg){
    console.log('error: ' + msg);
});

logger.emit('error', 'sth went wrong');

Same “#$! different packaging:

http.createServer(function(req, resp){}); 

//is the same as:

var server = http.createServer();
server.on("request", function(req, resp){};

Pip | ing:

var fs = require('fs');
var http = require('http');

http.createServer(function(request, response){
    var newFile = fs.createWriteStream('newFile.md');
    request.pipe(newFile);

    request.on('end', function(){
        response.end('uploaded');
    });
}).listen(8080);

//test like this:
curl --upload-file someFile.txt http://localhost:8080

File uploader:

var fs = require('fs');
var http = require('http');

http.createServer(function(request, response) {
	var newFile = fs.createWriteStream("readme_copy.md");
	var fileBytes = request.headers['content-length'];
	var uploadedBytes = 0;

	request.pipe(newFile);

	request.on('data', function(chunk) {
		uploadedBytes += chunk.length;
		var progress = (uploadedBytes / fileBytes) * 100;
		response.write("progress: " + parseInt(progress, 10) + "%\n");
	});

	request.on('end', function(){
        response.end('uploaded');
    });
}).listen(8080);

A side-note; console.log()  does in fact call process.stdout.write.

While calling your own modules, you require them without the “.js”

//custom_hello.js file
var hello = function() {
    console.log("hello!");
}
exports = hello;

//custom_goodbye.js file
exports.goodbye = function(){
    console.log("whot!?");
}

//--usage:
var hello = require('./custom_hello');
var gb = require('./custom_goodbye');

hello();
gb.goodbye();

When you’re requiring with “./” it searches in the current file directory. When, however, you search without it and just write the name of the module it first searches in the file directory for a folder named node_modules, then it goes folder up if it doesn’t find it in recursive.

npm install request  installs it locally and you can (only then!) require it in your code, whilst you should do a global installation  npm install coffee-script -g  if the module has an executable.

//package.json
{
  "name": "My Awesome Node App",
  "version": "1",
  "dependencies": {
    "connect" : "2.2.1",
      "underscore" : "1.3.3"
  }
}

package.json  file is cool as you can distribute the “barebones” app, which once downloaded can be fully installed by doing npm install  (it also installs sub-dependencies if needed).

Express – web application framework for Node.js: npm install express

var express = require('express');

var app = express(); //prior versions: express.createServer();
app.get('/:param', function(request, response){
    var param = request.params.param;
    response.send(param);

    //or, templates are also supported!
    response.render('tweet.ejs', {tweets: tweets, name: username});
});

app.listen(8080);

//tweet.ejs
<h1>Tweets for <%= name %></h1>
<ul>
    <% tweets.forEach(function(tweet)){ %>
        <li><%= tweet.text %></li>
   <% }; %>
</ul>

//but, also you need layout.ejs
<!DOCTYPE html>
<html>
    <head>
        <title>Some cool title</tile>
    </head>
    <body>
        <%- body %>
    </body>
</html>


Socket.IO
 – aims to make realtime apps possible in every browser and mobile device.
npm install socket.io

Simple chat application

var express = require('express'),
	app = express(),
   	server = require('http').createServer(app),
   	io = require('socket.io').listen(server);

server.listen(8080);

app.use(express.static(__dirname + '/'));

app.get('/', function (req, res) {
   	res.sendfile(__dirname + '/chat.html');
});

io.sockets.on('connection', function (client) {
   	client.on('join', function(name){
   		client.set("nickname", name);
   	});

   	client.on("msg", function(data){
      	client.get("nickname", function(err, name){
      		client.broadcast.emit('msg', name + ":" + data);
      	});
   	});
});

Very important thing to note here is that in order to make use of jQuery library you have to set the correct path to your js files in the app.use()  function.

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script src="/socket.io/socket.io.js"></script>
    <script src="jquery.js"></script>
    <script>
    $(document).ready(function(){
        var server = io.connect('http://localhost');

        server.on("connect", function(data){
            nickname = prompt("Your nickname:");

            server.emit("join", nickname);
        });

        server.on('msg', function(data){

           $('#recv').append(data + "<br/>");
	    });

	    $("#send").on("click", function(event){
            event.preventDefault();

            $('#recv').append($('#msg').val() + "<br/>");
    	    server.emit('msg', $('#msg').val());
    	});
    });
    </script>
</head>
<body>
    <input type="text" id="msg" name="msg" value="testets"/>
    <input type="submit" id="send" name="send"/>

    <div id="recv" name="recv"></div>
</body>
</html>

mongoDB –  open-source document database, and the leading NoSQL database written in C++. mongojs – A Node.js module for mongodb, that emulates the official mongodb API as much as possible. Installation via npm: npm install mongojs .

//db.js
var databaseURI = "mydb";
var collections = ["users"];
var db = require("mongojs").connect(databaseURI, collections);

module.exports = db;

//dbtest.js
var db = require("./db");

db.users.save({email: "[email protected]", group: "A"}, function(err, saved) {
  if( err || !saved ) console.log("User not saved");
  else console.log("User saved");
});

db.users.find({group: "A"}, function(err, users) {
  if( err || !users) console.log("No A group users found");
  else users.forEach( function(user) {
    console.log(user);
  });
});

In order for this to work mongoDB has to be installed on your system and it has to be running.  Installation instructions are clear and concise on their website, but a tl;dr is: download the zip package, unzip in c:\mongodb , make c:\data\db  folder, run c:\mongodb\bin\mongod.exe.

CodeProject, NodeJS

Using CasperJS on Webfaction to automatically send emails with attached images via Gmail

Why?

Recently I had to make a script which runs once per week and gathers images of an admin interface (login required) and sends it to its manager by email for quick overview. This is great because it saves the manager’s time as he doesn’t have to login to the website and click through all of the graphs and wait for them to load, instead he gets a weekly (YMMV) summary. The site was hosted on Webfaction, which, as it turns out, is a cool web host (haven’t come across it before) because it allows you to compile source code and run custom binaries.

How?

The task of automatically logging in the admin dashboard and taking screenshots  proved to be an excellent job for CasperJS, an open source navigation scripting & testing utility written in Javascript for the PhantomJS WebKit headless browser.

Installation

In order to run CasperJS scripts, you need to have NodeJS installed. Installing NodeJS on Webfaction is as straightforward as it can get, as it’s done via their control panel in the Applications tab, as shown on the illustration below:
webfactionNodeInstall

It’s useful to put NodeJS executable in your path because then you can run node from any folder. You can do this by going to your NodeJS application’s bin directory and execute the following command:

export PATH=$PATH:$PWD/bin/

Installing CasperJS is easy via npm (Node package manager):

npm install -g casperjs

However,  in order for CasperJS to work, you need to install PhantomJS and you can do it by cloning it from its GitHub repository and running the build.sh script:

mkdir -p $HOME/src

cd $HOME/src

git clone git://github.com/ariya/phantomjs.git && cd phantomjs

git checkout 1.5

./build.sh

cp $HOME/src/phantomjs/bin/phantomjs $HOME/bin

To test if PhantomJS has been successfully installed you can run:

phantomjs --version

To have the binaries in my path every time I log in I added this alias to my .bashrc:

alias nodeset="export PATH=$PATH:/home/webapp/node/bin:/home/webapp/bin"

and my .bash_profile looks like this:

# User specific environment and startup programs
PATH=$PATH:$HOME/bin
export PATH
nodeset

CasperJS script for automatically saving images

var casper = require("casper").create({
	verbose: false,
	logLevel: 'debug'
});

var url = "http://your-app.com/", 
	saveDir = "/home/app/savedImages";

casper.start(url, function() {
	this.fill('form#fm_login', {
        'username':    'username',
        'password':    'password',
    });

    this.echo("I filled the form");
});

casper.then(function(){
	this.click('#btn_login');
	this.echo("I'm, logging in");
});

//first graph fetch
casper.thenOpen("http://your-app.com/graph_1", function(){
    this.wait(3000, function() {
        this.echo("I've waited for 3 seconds for the graphs to load.");

        casper.then(function(){
            var fileName = saveDir + '/graph_1.png';
            this.viewport(1920, 1080);
            this.captureSelector(fileName, '#page_content');
            this.echo('first snapshot taken');
        });
    }); 
});

casper.run(function() {
    this.echo('done').exit();
});

First I initialize casper and set few variables (url, saveDir – note that it has to be full path). Then I start casper by visiting the passed in url and fill the login form by using caspers fill() function. After that I click on the login button and woila – I’m logged in. After that I open up the link with the graph and wait 3 seconds for the graph to load, and then I save the selected area by using the captureSelector() function and a CSS selector of the area I want to save.

NodeJS script for automatically sending email with attachment via Gmail SMTP

This node script uses nodemailer which can be installed using npm:

node install -g nodemailer

This script uses Gmail SMTP (if you want to test it make sure to enter correct Gmail account credentials), but nodemailer offers many more options for sending the email. The simple email sending script is here:

var nodemailer = require("nodemailer");
var rootFolder = "/home/app/savedImages/";
// create reusable transport method (opens pool of SMTP connections)
var smtpTransport = nodemailer.createTransport("SMTP",{
    service: "Gmail",
    auth: {
        user: "[email protected]",
        pass: "your.gmail.pass"
    }
});

// setup e-mail data with unicode symbols
var mailOptions = {
    from: "Automatic Graph Sender <[email protected]>", // sender address
    to: "[email protected]", // list of receivers
    subject: "Automatic Graph Sender", // Subject line
    text: "Hello, I'm Roboty, an automatic report sending robot. You will find your files in attachment. I wish you a great day! Bye, Roboty", // plaintext body
    html: "Hello,<br/><br/>I'm Roboty, an automatic report sending robot. You will find your files in attachment.<br/><br/>I wish you a great day!<br/><br/>Bye,<br/>Roboty",
    attachments: [
        { filePath: rootFolder + "graph_1.png"},
        { filePath: rootFolder + "graph_2.png"},
        //add as many as you wish
    ]
}

// send mail with defined transport object
smtpTransport.sendMail(mailOptions, function(error, response){
    if(error){
        console.log(error);
    }else{
        console.log("Message sent: " + response.message);
    }

    // if you don't want to use this transport object anymore, uncomment following line
    smtpTransport.close(); // shut down the connection pool, no more messages
});

 

Cron jobs

The following script will run every day at exactly 19:50h. I added the PHANTOMJS_EXECUTABLE needed by CasperJS executable, then I wrote the path to CasperJS and the script that we want to execute and finally I redirected all the output to the temporary file for later inspection if needed.

50 19 * * * PHANTOMJS_EXECUTABLE=/home/app/bin/phantomjs /home/app/node/bin/casperjs /home/app/casper/saveImages.js > /tmp/outputCheck.txt

Mailing script runs 5 minutes after the image gathering script and also outputs everything to the temporary file used in some other success status checking script.

55 19 * * * /home/emtool/webapps/node/bin/node /home/emtool/my_folder/casper/mail.node.js > /tmp/emailOut.txt

Hope this proved useful to someone, and hit me with comments or questions you may have.

CodeProject

Page 13 of 13« First...«10111213

Recent posts

  • Discipline is also a talent
  • Play for the fun of it
  • The importance of failing
  • A fresh start
  • Perseverance

Categories

  • Android (3)
  • Books (114)
    • Programming (22)
  • CodeProject (35)
  • Daily Thoughts (77)
  • Go (3)
  • iOS (5)
  • JavaScript (127)
    • Angular (4)
    • Angular 2 (3)
    • Ionic (61)
    • Ionic2 (2)
    • Ionic3 (8)
    • MEAN (3)
    • NodeJS (27)
    • Phaser (1)
    • React (1)
    • Three.js (1)
    • Vue.js (2)
  • Leadership (1)
  • Meetups (8)
  • Miscellaneou$ (77)
    • Breaking News (8)
    • CodeSchool (2)
    • Hacker Games (3)
    • Pluralsight (7)
    • Projects (2)
    • Sublime Text (2)
  • PHP (6)
  • Quick tips (40)
  • Servers (8)
    • Heroku (1)
    • Linux (3)
  • Stack Overflow (81)
  • Unity3D (9)
  • Windows (8)
    • C# (2)
    • WPF (3)
  • Wordpress (2)

"There's no short-term solution for a long-term result." ~ Greg Plitt

"Everything around you that you call life was made up by people that were no smarter than you." ~ S. Jobs

"Hard work beats talent when talent doesn't work hard." ~ Tim Notke

© since 2016 - Nikola Brežnjak