What should be my FAYE_URL value for Rails chat ap

2019-08-21 23:09发布

I am trying to make a Chat web application based on Rails using "private_pub" gem which works perfectly on my localhost server. Now my site is hosted on DigitalOcean and i want to push chat code on the server to see how real-time chat app will work.

This is my private_pub.yml file

development:
 server: "http://localhost:9292/faye"
 secret_token: "secret"
test:
 server: "http://localhost:9292/faye"
 secret_token: "secret"
staging:
 server: <%= ENV["FAYE_URL"] %>
 secret_token:"secret_key"
 signature_expiration: 3600 # one hour
production:
 server: <%= ENV["FAYE_URL"] %>
 secret_token: "secret_key"
 signature_expiration: 3600 # one hour

My question is What should i have to do to make it work on any Linux server ( Here Digital Ocean for me). I am using Nginx server on DigitalOcean.

What should be the value for FAYE_URL in private_pub.yml file?

rackup private_pub.ru -s thin -E production

Do i have to run rack command on my server terminal? Or is there any other way to host Faye on a different server then?

1条回答
走好不送
2楼-- · 2019-08-21 23:32

I don't know Digital Ocean's servers.
I have worked with a Google Cloud Engine virtual machine with OS Ubuntu 14.04.

Here's how I configured my pub/sub app that uses Faye with a dns resolver in HTTPS on Nginx web server with Passenger.

Faye Server

I set up the Faye server, as a Rack application, to start automatically at boot through the 'Thin' web server.

Script to start/stop Thin with params: thin-configuration-file, faye-rackup-server-script.

/home/user/apps/myapp/config/thin.sh

#!/bin/sh
set -e
TIMEOUT=${TIMEOUT-60}
APP_ROOT=/home/user/apps/myapp
PID=$APP_ROOT/tmp/pids/thin.pid
CMD="cd $APP_ROOT; thin -C $APP_ROOT/config/thin.yml -R $APP_ROOT/faye.ru"
AS_USER=user
set -u
startme() {
  run "$CMD start"
}
stopme() {
  run "thin stop"
}
run () {
  if [ "$(id -un)" = "$AS_USER" ]; then
    eval $1
  else
    su -c "$1" - $AS_USER
  fi
}
case "$1" in
  start)   startme ;;
  stop)    stopme ;;    
  restart) stopme; startme ;;
  *) echo "usage: $0 start|stop|restart" >&2
  exit 1
  ;
esac

so I set the execution permissions for the script thin.sh

chmod ugo+x /home/user/apps/myappconfig/thin.sh

-rwxr-xr-x 1 user user ... thin.sh*

then I defined the script thin.sh as a service

cd /etc/init.d
sudo ln -s /home/user/apps/myapp/config/thin.sh thin

lrwxrwxrwx 1 root root ... thin -> /home/user/apps/myapp/config/thin.sh*

and finally I configured the boot on startup

sudo update-rc.d thin defaults

I have defined the parameters necessary for the script thin.sh (as params in $CMD in config/thin.sh)

First the thin web server configuration file

/home/user/apps/myapp/config/thin.yml

chdir: "/home/user/apps/myapp"
environment: production
address: 127.0.0.1
port: 9292
timeout: 30
wait: 30
max_conns: 1024
log: /home/user/apps/myapp/log/thin.log
pid: /home/user/apps/myapp/tmp/pids/thin.pid
max_persistent_conns: 100
require: []
threadpool_size: 20
daemonize: true
ssl: true
ssl-key-file: "/etc/ssl/private/example_com.key"
ssl-cert-file: "/etc/ssl/certs/example_com.crt"
#ssl-disable-verify: true

and then the Faye server startup script (via rackup)

/home/user/apps/myapp/faye.ru

require 'eventmachine'
require 'rack'
require 'thin'
require 'faye'
# set FAYE_TOKEN you prefer for faye authentication
require File.expand_path('../config/initializers/faye_token.rb', __FILE__)
Faye::WebSocket.load_adapter('thin')
#define authentication extension 
class ServerAuth
  def incoming(message, callback)
    if message['channel'] !~ %r{^/meta/}
      if !message['ext'].nil?
        if message['ext']['auth_token'] != FAYE_TOKEN
          message['error'] = 'Invalid authentication token'
        end
      end
    end
    if message['channel'] =~ %r{/meta/subscribe}
      ...
    end
    callback.call(message)
  end
end
faye_server = Faye::RackAdapter.new(:mount => '/faye', :timeout => 30)
faye_server.add_extension(ServerAuth.new)
run faye_server

at this point the automatic start of faye server is set.
At boot '/etc/init.d/thin' service start 'thin server' with config/thin.yml executnig rackup script 'faye.ru'.

Faye client

I parametrized the urls for faye client

/home/user/apps/myapp/config/initializers/urls.rb

FAYE_MOUNTPOINT_URL='https://example.com/faye'
FAYE_JSCLIENT_URL='https://example.com/faye/client.js'

I included faye client javascripts in

/home/user/apps/myapp/app/views/layouts/application.html.erb

so then they are charged when you access the app

<!DOCTYPE html>
<html lang="it">
<head>
  <%= javascript_include_tag FAYE_JSCLIENT_URL %>
</head>
...

The Faye client is created when you access the page where there are your chat rooms (as channel).
The right place is

/home/user/apps/myapp/app/assets/javascript/application.js

...
var faye = null;
$(document).ready(function(){
  // https
  faye = new Faye.Client('<%= FAYE_MOUNTPOINT_URL %>');
  faye.disable('autodisconnect');
  // divs with '.subscribe' class contain channels name
  $('.subscribe').each(function() {
    // subscribe each channel
    faye.subscribe('/'+$(this).text(), function (data) {
      // here I process 'data' to refresh page with new content using jquery
      // I'm using hidden div
      // when I receive notification I clone hidden div, then I fill some fields and I exhibit the new cloned div
      ...
      msg = $('#message_template').clone();
      msg.html(data.message.content);
      msg.css('visibility','visible');
    });
  });
});

Sending a new message from client to server Faye:
(creating a new Message model with a call remote: true (ajax))

called by create.js rensponse triggerd by controller_message#create as ajax response renderer

/home/user/apps/myapp/app/helpers/application_helper.rb

def broadcast(channel, <your_params>)
  # prepare 'data' as json format
  data = { your_key: your_params.as_json }
  message = { channel: '/' + channel.name, data: data, ext: { auth_token: FAYE_TOKEN } }
  # https
  uri = URI.parse(FAYE_MOUNTPOINT_URL)
  Net::HTTP.post_form(uri, message: message.to_json, use_ssl: true)
end

That's all

For a better comprehension, I enclose Nginx configuration file

worker_processes  1;
error_log   logs/err.log debug;
events {
  worker_connections  1024;
}
http {
  upstream faye {
    server unix:/tmp/faye.0.sock;
    server unix:/tmp/faye.1.sock;
  }
passenger_root /home/user/.rvm/gems/ruby-2.3.0/gems/passenger-5.1.11;
server {
  listen 80;
  server_name example.com;
  return 301 https://example.com/$request_uri;
}
server {
  listen 443 ssl default_server;
  server_name example.com;
  ssl_certificate   /etc/ssl/certs/example_com.crt;
  ssl_certificate_key /etc/ssl/private/example_com.key;
  ssl on;
  passenger_enabled on;
  passenger_app_root /home/user/apps/myapp;
  passenger_ruby /home/user/.rvm/gems/ruby-2.3.0/wrappers/ruby;
  location / {
    root /home/user/apps/myapp/public;
  }
  error_page   500 502 503 504  /50x.html;
  location = /50x.html {
    root   html;
  }
  location /faye {
    proxy_pass https://127.0.0.1:9292/faye;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_redirect off;
  }
}
查看更多
登录 后发表回答