Socket.io and nginx workaround

If you are running a node.js app, it is a good idea to use a reverse proxy (nginx, HAproxy) along side of it.  The main reason being that you aren’t wasting precious cycles on your single threaded node.js server by making it serve static content (javascript, images, css, etc).  nginx and node.js work great together.  Unfortunately, most node.js apps rely on websockets, which are a new HTML5 standard that allows full duplex communication between client and server.  I say “unfortunately” because most reverse proxies do not support websockets inherently.  So if you aren’t a sys admin or server guy, adding, compiling and configuring a reverse proxy module isn’t trivial.  The good news: there is a pure javascript workaround.

Ideally, a sample workflow would look like this:

  1. nginx listens on port 80
  2. nodejs listens on port 8080
  3. socket.io listens on port 8080 through nodejs app
  4. nginx proxies any requests on port 80 over to nodejs on 8080
  5. socket.io client connects directly to node/socket server on port 8080 and communicates directly without involvement of a reverse proxy

Following is the gist I wrote of the code to do it:

Complete Nodejs Environment Setup

Step by step instructions that I have compiled through many hours of working with Nodejs.  Instructions include installation and configuration of: Ubuntu, Nodejs, Nginx, MongoDB, Redis and NPM modules.  You can find the original post here: https://gist.github.com/1998987 

SQL Bulk Inserts

MySQL allows you to insert multiple rows with one statement.  Take a look at this basic bulk insert syntax:

INSERT INTO destination_table (destination_field)
SELECT target_field FROM target_table;

This saves you from querying the database, looping through the results, and inserting on each iteration.

You are also able to insert multiple columns as well:

INSERT INTO destination_table (destination_field_one, destination_filed_two)
SELECT target_field_one, target_field_two FROM target_table;

Website From Scratch

Being my first blog post, I find it fitting to share how I actually got this site up and online in hopes that it might benefit someone else looking to accomplish the same thing.

Start by purchasing a domain name.  I chose GoDaddy.com.  Make sure that you google for promo codes before you actually buy the domain.  There is a good chance that you will find something that can save you a considerable amount.

If you bought your domain name from GoDaddy and choose to host your site with them as well, you won’t need to make any necessary changes pertaining to your domain name.  But if you choose to host with a different hosting company (such as Rackspace), you will need to log in to GoDaddy and update your name servers.  The name servers will be provided to you by the company that you are hosting with.  The name servers for Rackspace are DNS1.STABLETRANSIT.COM and DNS2.STABLETRANSIT.COM respectively.

Next, buy some server space.  Many options are available including cloud and dedicated servers.  Dedicated server will cost substantially more, but provide better performance.  In both cases, the steps needed to install the correct software are the same.  If you bought a server from Rackspace, log into the control panel.  You will need to install an Operating System.  I chose Ubuntu 10.10.  It only takes minutes for the server to install your OS and soon after you will have an entry in your servers table.  Click on the name of your server to continue configuration.  This will bring you to a control panel where there are helpful tools such as resizing and rebooting your server.  For now, click on the DNS tab.  Under the “Domain Management” heading, click “add” to add a domain.  Enter your domain name here (yoursite.com) and click OK.  This will add your domain to the table.  Click on your domain to continue configuring.  Here, you will enter in three DNS records: Types A, CNAME, and MX.  Configuration goes as follows:

Type: AName: yoursite.com (make sure you do NOT add www.)Content: your IP Address (34.234.45.32)TTL: 300Type: CNAMEName: www.yoursite.com (make sure you DO add www.)Content: yoursite.com (make sure you do NOT add www.)TTL: 300Type: MXName: yoursite.com (make sure you do NOT add www.)Content: yoursite.com (make sure you do NOT add www.)TTL: 300Priority: 10

Now that your domain name and host are configured, you need to install the lamp stack.  Fortunately in Ubuntu 10.10, you are able to install Apache2, PHP5, MySQL and all the inter-dependencies with one line.

SSH into your server via the IP address that your hosting company has given you.  Once authenticated, type the line:


sudo apt-get install lamp-server^

Make sure you have that carrot at the end, or this command will not work properly.  About half way through set up, it will prompt you to create a password for the root user in MySQL.  Do not forget this password, it is a headache if you do.  When installation has completed, navigate to your Apache configuration file.  It can be found in: /etc/apache2/apache2.conf.  After the line #ServerRoot “/etc/apache2″, add this Directive:

ServerName yoursite.com:80

If you want to allow virtual hosts on your server, navigate over to your httpd configuration and open it up.  It is located in /etc/apache2/httpd.conf.  Enter the following code and save the file (this is assuming you will make a directory called “yoursite” in /var/www):

# Ensure that Apache listens on port 80
Listen 80


# Listen for virtual host requests on all IP addresses
NameVirtualHost *:80


<VirtualHost *:80>
DocumentRoot /var/www/yoursite
ServerName www.yoursite.com


ServerAlias yoursite.com


</VirtualHost>

Next, navigate to the ports configuration.  It is located in /etc/apache2/ports.conf.  Comment out the lines (because you have now defined them in your httpd.conf):


NameVirtualHost *.80


Listen 80

From the command prompt, run the command (to enable mod_rewrite):

sudo a2enmod rewrite

Once this has finished installing, restart Apache!

sudo /etc/init.d/apache2 restart

Your LAMP stack is now ready for action.

Safely Storing Passwords Conveniently

I have so many accounts with different usernames and passwords that it is impossible to remember all of them.  I found myself always clicking the “forgot password” link and resetting my passwords every time I’ve needed to log in to an account I haven’t used in a while.  There has to be a better way.

There is.

Enter Dropbox, KeePass and Ubuntu.  Well, Ubuntu isn’t necessary, but it is my OS of choice.

Dropbox is straight forward.  It auto-installs on pretty much any OS, so if you don’t have it, head over to http://www.dropbox.com to download and create an account.

KeePass is straight forward as well, except if you are running Ubuntu, as I am.  It takes a little more fidgeting to work.  First, Mono needs to be installed on your system.  If you are running a more recent version of Ubuntu, it comes pre-packaged, so you don’t have to worry about it.  You are going to need to install the winforms library though.  Luckily this can easily be found in the ubuntu software center:

Open ubuntu software center and search “winforms”.

Install the entry that reads “Mono System.Windows.Forms library (for CLI 2.0).

Now that everything is ready to go, head on over to the KeePass website download page: http://keepass.info/download.html and download the Portable KeePass 2.16 (ZIP Package).  Unzip this package to whatever location that you want.  In my case it was /home/nate/keepass

While you are on this page, download that KeePass icon in the top left corner and save it to the same folder you unzipped your package to..you can use it for a launcher Icon.

Right click on your launcher panel, select “Add to Panel”, then choose “Custom Application Launcher”.

When the menu comes up, make sure the type is “Application”, the name is “KeePass” and the command is “mono /home/nate/keepass/KeePass.exe” where the path to your KeePass.exe is actually where you unzipped your package to.  Next click on that icon and choose the KeePass image that you saved from the KeePass site.

Click on your KeePass launcher Icon to open KeePass.  Once open, click File -> New.. to create a new KeePass database.  Point your file browser to your Dropbox folder and name your KeePass database whatever you would like.  Once saved, you now have access to your usernames and passwords wherever you have a KeePass client installed!

jQuery Clone

While writing some code today, I came across an interesting situation.  I was trying to copy an unordered list from one part of the page to another part of the page.  It seemed like a remedial task, so I started coding:

var myList = jQuery("ul#list");

jQuery("div#destination").append(myList);

but, I was surprised to see when I refreshed the page that the original list was gone, and it appeared in the new location.  This code acted just like a move rather than a copy.  Enter jQuery clone.  Using jQuery clone allows you to copy DOM elements instead of move them, so that your original elements remain:

var myList = jQuery("ul#list").clone(true);

jQuery("div#destination").append(myList);

The parameter passed to the clone function allows you to copy the data and binded events associated with the target element.

Javascript Objects

An object in javascript is a very powerful way of representing key – value pairs.  But, it is not without quirks.  Here is a brief overview of some useful features of the javascript object.

To create an empty object, use this line of code:

var myObject = {};

Now you have an empty javascript object.  You could also create an object with data as well:

var myObject = {natesAttribute:"Some data"};

Now, to add data to this object:

myObject.natesAttribute = "Some data";

or

myObject["natesAttribute"] = "Some data";

The first way is for when you know the name of the key that you want to set, the second is used normally when you are creating keys on the fly (i.e. in a loop), and can be used with a variable:

myObject[someVariable] = "Some data";

Also, it is helpful to know that you can nest objects to make them multidimensional:

myObject.natesAttribute = {aSubAttribute:"More data"};

To access the data in an object, use the same syntax as setting it (without actually setting it):

console.log(myObject.natesAttribute);

or

console.log(myObject["natesAttribute"]);

For a multidimensional object, keep stringing the dots:

console.log(myObject.natesAttribute.aSubAttribute);

Command Line PHP

PHP is most commonly executed when a user browses to a page that corresponds to that PHP file.  But sometimes it is useful to execute a PHP script right from the command line.  To do this is simple:

php /path/to/your/file.php

If you are having problems getting this to work, you can try adding the full path to PHP as well:

/path/to/php /path/to/your/file.php

Any PHP code in “file.php” will get executed just like it would if called from the browser.  The only difference is that the standard output is the command prompt instead of the browser, so that you are able to see the output of your script.

Now, to make this even more powerful, you can make your PHP script act as a global linux command.  This will allow you to call “fille.php” like you would a “cp” or “mv” linux command.  You are even able to pass parameters to it.  Here is how:

  1. Remove the .php extension from your file.  ”file.php” will now just be “file”.  You can name it anything you want to (i.e. “nathan.php” would become just “nathan”).
  2. Add a shebang as the first line of code inside “file”, even before the opening PHP tag.  The shebang should point to the PHP interpreter and will look a lot like this: #!/usr/bin/php or this: #!/usr/local/bin/php
  3. Move “file” to the list of available linux commands.  This is usually found in /usr/bin/ and you will probably need to invode sudo to move it there.

“file” should now look like this:

#!/usr/bin/php

<?php

echo "Hello World!\n";

?>

To call “file”, you simply need to write “file” without the quotes from the command line.

If you want the user to be able to pass parameters to this file, make use of the $argv variable available to you in PHP.  To pass parameters to your new command, simply separate them by spaces:

file test1 anothertest

“test1″ and “anothertest” will then be available to use through the use of $argv array in PHP.

MySQL Row Count

If you have ever needed to display data out of large databases, undoubtedly you have run across the issue of displaying the total available rows as well. This plays hand in hand with pagination where you want to show the current rows plus total rows (i.e. 20 -30 of 78). There are many ways to do this, but some definitely more efficient than others.

First, you could run your query with all constraints and a limit. Then you could run the same query without the limit and count the rows with PHP’s built in count function:

//get the first ten rows
$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
LIMIT 0,10');
$sth->execute();
$first_ten_rows = $sth->fetchAll();

//get all rows
$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit');
$sth->execute();
$ready_to_count = $sth->fetchAll();
$total_count = count($ready_to_count);

You are probably saying, why don’t you just use MySQL’s built-in count function right in the first query. Good point.

$sth = $dbh->prepare('SELECT COUNT(fruit_id) AS total, name, colour, calories
FROM fruit
LIMIT 0,10');
$sth->execute();
$first_ten_rows = $sth->fetchAll();

But MySQL’s count function my have unintended consequences and unnecessary overhead. For every record that is retrieved, MySQL will calculate the total number of rows. If your database if large, this could be considerable overhead. Not to mention, if you are using a GROUP BY in your SQL statement, MySQL’s count function will return the total number of rows in that group. Probably not what you are looking for.

That brings us to why MySQL has developed SQL_CALC_FOUND_ROWS. Using this keyword will allow MySQL to find all qualifying rows (excluding LIMIT) that you are able to retrieve very quickly in a separate statement:

$sth = $dbh->prepare('SELECT SQL_CALC_FOUND_ROWS name, colour, calories
FROM fruit
LIMIT 0,10');
$sth->execute();
$first_ten_rows = $sth->fetchAll();

$sth = $dbh->prepare('SELECT FOUND_ROWS()');
$sth->execute();
$total_count = $sth->fetch();

The FOUND_ROWS() function will return the number of rows in the previously executed select statement had it not had a limit associated to it.

More information can be found here:
http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_found-rows

Group Permissions

Working as a developer of part of a team can be frustrating when dealing with file permissions. Often times I have tried to make a quick change to a file only to find out I’m not able to write to it. To further complicate things, each IDE, FTP program, and file explorer has their own settings, all defaulting to something different. Fortunately, if you are working off a linux system, there are ways to combat this problem

1. Command Line

If you aren’t afraid to open up the command line, you can easily change group permissions in a noninvasive way.  It is common to see the chmod command used this way:

chmod -R 775 /path/to/your/directory

But this will change permissions for the owner, group and all.  In many cases dealing with team development, you only want to target the group permissions, while leaving the others intact.  To do this, use the chmod command in symbolic mode:

chmod -R g+w /path/to/your/directory

The “-R” will recursively step through each directory and file inside the targeted path.  The “g” stands for group.  If you wanted to just change the owner permissions, you would change this letter to “o”.  Likewise, to change the all permissions, you would change this letter to “o”.  The “+” means you are adding permissions.  If you would like to take away permissions, this would be changed to a “-”.  Lastly, you need to specify what kind of permissions you are adding (or subtracting).  In this case I am adding write permissions (“w”).  You are also able to add read (“r”) and execute (“x”).

For more information check out the chmod MAN page: http://ss64.com/bash/chmod.html

2. Filezilla

Filezilla is a common FTP program that makes this process very easy by using a GUI.  To change JUST the group permissions of a directory you simply right click on the directory that you want to affect and select “File Attributes…”:

file attributes 755

Now you have the option to set read, write and execute permissions on owner, group and all either by selecting checkboxes, or typing in the corresponding  three digit number.  If you look closely, you can read the line “You can use an x at any position to keep the permission the original files have.”.  This allows us to target only the group by placing an “x” instead of a number for the owner and all positions:

file attributes x7x

Once you click “OK”, the group permissions will change to read and write throughout the directory.