Node.js and nginx
This took me some time to figure out, and I didn’t see any detailed posts or bug reports on how to fix this. Nginx doesn’t support HTTP 1.1 on proxy pass, meaning, when you place Node.JS behind a proxy (for load balancing purposes, or you just have multiple endpoints on port 80), websockets will not work properly, since HTTP 1.1 is a core requirement. You’ll know, when you get errors similar to this:
Error during WebSocket handshake: 'Connection' header value is not 'Upgrade' XMLHttpRequest cannot load ***. Origin *** is not allowed by Access-Control-Allow-Origin.
I’m running nginx 0.6.8, with nginx 1.0.11. To fix this, you need to upgrade to a later version of nginx (a development version), which supports HTTP 1.1 (albeit, experimentally), and then enable the proxy_http_version 1.1 parameter in your vhost configuration.
I’m doing this on Ubuntu.
First, let’s compile nginx:
cd /usr/src wget http://nginx.org/download/nginx-1.1.13.tar.gz sudo tar xzvf nginx-1.1.13.tar.gz cd nginx-1.1.13 sudo ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin --with-http_ssl_module sudo make; sudo make install /usr/sbin/nginx -V # Something like this should show: nginx version: nginx/1.1.13 built by gcc 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3) TLS SNI support enabled configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin --with-http_ssl_module
Next, we setup our vhost:
server {
listen 80;
server_name node.domain.com;
location / {
proxy_pass http://localhost:8000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_redirect off;
proxy_http_version 1.1;
}
}
And now no more errors, and nodejs is working properly. Do note that this is a “bleeding edge” version of nginx, and could come with its own share of issues – so keep an eye out and test thoroughly!
Edit: If you’re still running into some problems, you can enable only xhr-polling/jsonp-polling in your Node.JS/socket.io configuration:
io.set('transports', [
'xhr-polling',
'jsonp-polling'
]);
Domain updated!
I’m now using “nabeelio.com” – since it’s been my long-time nickname, and nsslive just doesn’t mean anything anymore. All links have been updated, the old site will just redirect here. Cheers!
Sphinx and CakePHP
For a project, I’ve decided to use the Sphinx search engine, and was looking for behaviors for CakePHP, to just make it much easier to implement. Since I’m using Cake 2.0, I could only find something that was for < Cake 1.3. So I decided to update it for use with Cake2.0, and it’s working beautifully with pagination.
It’s located in my github site:
https://github.com/nshahzad/Sphinx-CakePHP
The usage is exactly the same as the original (the link to it is above). The only thing is that it’s assuming you have the sphinxapi.php (which comes with the Sphinx source) extracted into Vendor/sphinxapi/sphinxapi.php (that’s where App::import() will look for it).
Installing Redmine on Ubuntu 11.04 w/nginx and mongrel
This one took me a few hours, but I’ve got my handy-dandy notes. I’m going to assume you’re got nginx installed, whether there are vhosts or not…
I’m also installing to /var/www/redmine
sudo apt-get install mongrel ruby gems cd /var/www wget http://rubyforge.org/frs/download.php/75097/redmine-1.2.1.tar.gz tar xzvf redmine-1.2.1.tar.gz mv redmine-1.2.1 redmine sudo chown www-data: redmine -R sudo chmod 775 redmine -R
Next, we are going to patch Redmine, to work with Mongrel
cd /var/www/redmine/config/initializers/ wget http://www.redmine.org/attachments/6146/rails_6440_patch.rb wget https://gist.github.com/raw/826692/cb0dcf784c30e6a6d00c631f350de99ab99e389d/mongrel.rb sudo chmod 775 . -R sudo chown www-data: -R
Next, setup the right versions of Rails, etc
gem install -v=2.3.14 rails gem install rack -v=1.1.1 gem install rake -v0.8.7
Now setup MySQL:
mysql -uroot -p create user 'redmine'@'localhost' identified by 'password'; grant all privileges on `redmine%` . * to 'redmine'@'localhost'; create database redmine character set utf8;
And next, we configure and run the installer for Redmine. We are going to edit the database.yml, set it to match your above settings
cd /var/www/redmine/config mv database.yml.production database.yml nano database.yml cd /var/www/redmine rake generate_session_store RAILS_ENV=production rake db:migrate RAILS_ENV=production rake redmine:load_default_data
Next, we start the server
mongrel_rails start -e production -p 9001 -d
Next, create the nginx vhost, I created it as /etc/nginx/sites-enabled/redmine
server {
listen 80;
server_name YOUR_HOSTNAME_HERE;
root /var/www/redmine/public;
#error_log /var/log/nginx/redmine.log debug;
expires epoch;
location / {
expires epoch;
alias /var/www/redmine/public/;
try_files $uri/index.html $uri.html $uri @mongrel;
}
location @mongrel {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_pass_header Set-Cookie;
proxy_pass http://127.0.0.1:9001;
}
}
MySQL Diff Tool
After searching for a while, I haven’t been able to find a tool which will show the diffs between two MySQL Databases. There are plenty to handle migrations, but migrations are tough when you’re writing an app which is install by an end-user. So I wrote a tool/class which will take the XML of a proper database (that file can be distributed in your package), and then will compare the XML schema against the schema in the current database.
Generate a MySQL Dump file:
mysqldump --xml --no-data testuser -utestuser -ptest1 > structure.xml
Then call the command line script (diffgen):
diffgen -utestuser -ptest1 -dtestuser -hlocalhost -fstructure.xml -tshow
-u Database User
-p Database Password
-d Database Name
-h Database Host
-f Dump File Path
-t "show" or "run" - show will output the SQL, "run" will run the SQL
There’s also a class file (which it is all from), which you can use to integrate into your own custom scripts (as-is the case with phpVMS, which is distributed with the structure.xml that is generated by my Phing build process, and it “shapes” the database on the remote server properly in an update script).
The script can be downloaded from https://github.com/nshahzad/MySQLDiff
Amazon PHP API
I couldn’t find a working PHP class for the Amazon API, which had Exception handling and some versatility. So I wrote one up. It’s a work-in-progress at the moment, but it’s available on GitHub:
http://github.com/nshahzad/AmazonAPI
The included README has detailed instructions. The class uses the __call() functionality, and you just pass the required parameters as a dictionary array. Requires some reading of the Amazon docs, but much more flexible.
PHP class for Google Geocoder API
For a project I’ve been working on, I needed to access Google’s Geocoder API. I search for names (schools in this case), and return as much info as I can that Google has about it.
I’ve posted the class up on Github, it’s straightforward, and might help some people out:
http://github.com/nshahzad/Google-Geocoder
The usage is in the readme/displayed right on the github page. It uses cURL and JSON to keep the traffic transfered low. That also means you need the json_decode() function, which is in PHP 5.2 and up.
Happy 4th!
Building php-fpm against Ubuntu PHP Packages
This is how I’ve been building php-fpm against the Debian PHP packages. It’ll be useful for when Ubuntu 10.04 (Lucid Lynx) Comes out with PHP 5.3. I do this from my home directory. It will download the package souce from Ubuntu, then compile php-fpm standalone against that.
Then, configure the php-fpm file. That should be it
A better way for nginx PHP config
Doing some reconfiguration on my webserver (nginx) to make it easier to administer. My first goal was to get rid of this nastiness:
server {
...
location ~ \.php$ {
include /etc/nginx/conf/fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/path/to/$fastcgi_script_name;
}
}
It’s too verbose to copy/paste into each virtual host file. Instead, you can just combine the file into the /etc/nginx/conf/fastcgi_params file. I renamed it to php_params, and this is what it’s got:
location ~ \.php(.*)$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
}
Now I don’t have to change it everywhere. So, instead, now I do:
server {
...
# Include the PHP Fast-CGI Params
include /etc/nginx/conf/php_params;
}
Bam! 6 lines down to one, and much easier to administer. I like, I like.
PHP Resources
I put a list together for a friend of some good PHP resources, thought I’d stick it up here as well:
Of course, the best resource, the official docs:
http://www.php.net
Another great (official) place:
http://talks.php.net/
The talks are by the creators of PHP. Any talks by Rasmus Lerfdorf are excellent, he stresses simplicity over complexity. He’s also the creator of PHP. Derick Rethans is also an excellent presenter, he focuses a lot on security and debugging. Definitely watch the presentations in the “Security” section of the talks, but overall, any talk in there has information you can use to your advantage.
Other sites:
http://www.smashingmagazine.com/2009/03/24/10-useful-php-tips-revisited/
http://php.about.com/od/advancedphp/Advanced_PHP.htm
Sitepoint is where I first started learning HTML and CSS many years ago:
http://www.sitepoint.com/subcat/php-tutorials
MVC tutorials (how apps should be coded; obviously there’s some contention between OO and procedural styles, but you need knowledge of both to be able to make an educated judgment about what a good balance between the two is)
http://www.phpro.org/tutorials/Model-View-Controller-MVC.html
Good to go through to understand MVC completely
CakePHP has a good introduction:
http://book.cakephp.org/view/10/Understanding-Model-View-Controller
Which brings me to CakePHP itself. It’s an excellent MVC framework; after trying out CodeIgniter, Zend, Yii, Kohana, I’ve settled on Cake.
http://cakephp.org/
SQL resources – the best is the manual. Learning the concepts behind joins is essential and important. A good tutorial:
http://www.codinghorror.com/blog/archives/000976.html
Also database design:
http://www.simple-talk.com/sql/database-administration/ten-common-database-design-mistakes/
http://woork.blogspot.com/2008/09/10-useful-articles-about-database.html
Following that up are good ORM, which you may want to use as your database layer. CakePHP has ORM built-in, but sometimes all you need is just a DB layer.
http://www.doctrine-project.org/
For conventions, I tend to follow the CakePHP model (since that’s the framework I use the most):
http://book.cakephp.org/view/24/Model-and-Database-Conventions
http://bakery.cakephp.org/articles/view/database-design-and-cakephp
http://book.cakephp.org/view/22/CakePHP-Conventions
And then rounding it out, some general knowledge information:
http://articles.sitepoint.com/category/html
http://articles.sitepoint.com/category/javascript
http://articles.sitepoint.com/category/cssh
http://www.jquery.com