Search code examples
ruby-on-railsnode.jsfaye

Faye with nodejs over HTTPS


I'm trying to setup my production server to use faye messages using nodejs and HTTPS, but no luck.

What I have until now is:

A faye + nodejs server setup file:

var https = require('https');
var faye = require('faye');
var fs = require('fs');

var options = {
    key: fs.readFileSync('/etc/httpd/ssl/example.com.key'),
    cert: fs.readFileSync('/etc/httpd/ssl/example.com.crt'),
    ca: fs.readFileSync('/etc/httpd/ssl/ca_bundle.crt')
};

var server = https.createServer(options);
var bayeux = new faye.NodeAdapter({mount: '/faye', timeout: 60});

bayeux.attach(server);
server.listen(8000);

A rails helper to send messages:

def broadcast(channel, &block)
  message = {:channel => channel, :data => capture(&block)}
  uri = URI.parse(Rails.configuration.faye_url)
  Net::HTTPS.post(uri, message.to_json)
end

A javascript function to open a listener:

function openListener(channel, callback){
    var faye_client = new Faye.Client("<%= Rails.configuration.faye_url %>");
    faye_client.subscribe(channel , callback);
    return faye_client;
}

My faye url config in production.rb:

config.faye_url = "https://example.com:8000/faye"

And finally, a call in my page javascript:

fayeClient = openListener("my_channel" , function(data) {
    //do something...
});

Everything was working when testing over http on development machine. But in production don't.

If I point browser to https://example.com:8000/faye.js I got the correct javascript file.

What could be happen?


Solution

  • The problem was with Apache server.

    I had switch to nginx and now it´s working.

    However, I need to make some configurations:

    Faye + node.js setup file:

    var http = require('http'),
        faye = require('faye');
    
    var server = http.createServer(),
        bayeux = new faye.NodeAdapter({mount: '/faye', timeout: 60});
    
    bayeux.attach(server);
    server.listen(8000);
    

    Rails helper:

    def broadcast(channel, &block)
      message = {:channel => channel, :data => capture(&block)}
      uri = URI.parse(Rails.configuration.faye_url)
      Net::HTTP.post_form(uri, :message => message.to_json)
    end
    

    Faye url:

    https://example.com/faye
    

    And finally, nginx config

    server {
        # Listen on 80 and 443
        listen 80;
        listen 443 ssl;
        server_name  example.com;
        passenger_enabled on;
        root /home/rails/myapp/public;
    
        ssl_certificate /home/rails/ssl/myapp.crt;
        ssl_certificate_key /home/rails/ssl/myapp.key;
    
        # Redirect all non-SSL traffic to SSL.
        if ($ssl_protocol = "") {
                rewrite ^ https://$host$request_uri? permanent;
        }
    
        location /faye {
            proxy_pass http://127.0.0.1:8000;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        }
    }
    

    Short words: nginx convert https requests in /faye address, to http in port 8000. Use default http in server side, and https in client side.