Skip to content

Instantly share code, notes, and snippets.

@mnutt
Created October 26, 2009 02:55
Show Gist options
  • Select an option

  • Save mnutt/218400 to your computer and use it in GitHub Desktop.

Select an option

Save mnutt/218400 to your computer and use it in GitHub Desktop.
== NGINX HTTP PUSH ==
Steps to reproduce:
Install passenger gem:
sudo gem install passenger
Download nginx:
wget http://sysoev.ru/nginx/nginx-0.7.62.tar.gz
tar -zxvf nginx-0.7.62.tar.gz
##HACK##
Edit nginx-0.7.62/auto/cc/gcc and search for -Werror and change it to -Wno-error
Otherwise the nginx compile will fail because of warnings in the http push module.
I expect this will be fixed very soon, possibly by the time you read this.
Clone the nginx http push module:
git clone git://github.com/slact/nginx_http_push_module.git
Use the passenger script to install nginx with support for passenger and long polling:
sudo passenger-install-nginx-module --nginx-source-dir=/path/to/src/nginx-0.7.62 \
--extra-configure-flags="--add-module='/path/to/src/nginx_http_push_module'"
Be sure to specify absolute paths.
Edit /opt/nginx/conf/nginx.conf and make it look something like this:
(make sure to change /path/to to point to the correct directories)
############################## SAMPLE NGINX ################################
worker_processes 1;
events {
worker_connections 1024;
}
http {
passenger_root /path/to/passenger-2.2.5;
passenger_ruby /path/to/bin/ruby;
include mime.types;
default_type application/octet-stream;
#maximum amount of memory the push module is allowed to use
#for buffering and stuff
push_max_reserved_memory 12M;
push_queue_messages off;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root /path/to/your/rails/application/public;
index index.html index.htm;
passenger_enabled on;
rack_env development;
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
#sender
location /send {
allow 127.0.0.1;
deny all;
default_type text/plain;
set $push_channel_id $arg_id; #/?id=239aff3 or somesuch
push_publisher;
push_message_timeout 2h; #buffered messages expire after 2 hours\
}
#receiver
location /listen {
push_subscriber;
push_subscriber_concurrency broadcast;
set $push_channel_id $arg_id; #/?id=239aff3 or somesuch
default_type text/plain;
}
}
}
########################### END SAMPLE NGINX #############################
The ruby/rails app just needs to do a post to localhost/listen. I'm doing
it in-process for now since nginx is on the same box and very responsive,
but there could be reliability implications.
########################## START RUBY EXAMPLE ############################
class MessagesController < ApplicationController
def create
@msg = Message.new(:content => params[:content], :user => current_user)
if @msg.save
http = Net::HTTP.new("localhost", 80)
http.post "/send/?id=messages", @msg.to_json
render :json => {:response => 200}
else
render :json => {:response => 500, :errors => @msg.errors }
end
end
def index
render :json => Message.all.to_json
end
end
########################## END RUBY EXAMPLE ##############################
To fetch new messages in javascript you need to hold an ajax connection open.
This example uses jQuery:
########################## START JS EXAMPLE ##############################
var newMessage = function(data) {
console.log(data);
};
// From http://stackoverflow.com/questions/333664/simple-long-polling-example-code
// (by dbr)
function waitForMsg(){
/* This requests the url "msgsrv.php"
When it complete (or errors)*/
$.ajax({
type: "GET",
url: "/listen?id=messages",
async: true, /* If set to non-async, browser shows page as "Loading.."*/
cache: false,
timeout:50000, /* Timeout in ms */
dataType: 'json',
success: function(data){ /* called when request to barge.php completes */
newMessage(data); /* Add response to a .msg div (with the "new" class)*/
setTimeout(
'waitForMsg()', /* Request next message */
1000 /* ..after 1 seconds */
);
},
error: function(XMLHttpRequest, textStatus, errorThrown){
console.log("error " + textStatus + " (" + errorThrown + ")");
setTimeout(
'waitForMsg()', /* Try again after.. */
"4000"); /* milliseconds (15seconds) */
},
});
};
$(function() { waitForMsg(); } );
########################## END JS EXAMPLE ##############################
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment