Skip to content
This repository has been archived by the owner on Dec 12, 2021. It is now read-only.

private_pub.js changes: only load faye.js if Faye object is not present and use module pattern to prevent pollution of global namespace #51

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
bc81f1e
Added basic support for using Redis engine.
zlu Feb 22, 2012
045975d
Added configuration instruction for Redis engine
zlu Feb 22, 2012
fe71d80
fixed mount point
zlu Feb 22, 2012
1f753ba
Refactor - Redis options are now passed into PrivatePub.faye_app.
zlu Feb 23, 2012
38726f8
Added some debugging
zlu Feb 23, 2012
33969eb
Changing how redis config is loaded
zlu Feb 23, 2012
00ecd3f
Setting default rails_env to be development
zlu Feb 23, 2012
298c3ed
Increased timeout to 60
zlu Feb 28, 2012
1f3728f
Fixed faye version to be 0.7.1 because thin was removed in a later ve…
zlu Feb 28, 2012
b17035c
Only sign when PrivatePub is avaiable. When thin server is down, Pri…
zlu Mar 5, 2012
ff647fa
Added logic to check in Faye server is up. Only subscribe when it is…
Mar 6, 2012
2a753a6
Revert "Added logic to check in Faye server is up. Only subscribe wh…
Mar 6, 2012
265c3bf
Added support to Faye 0.8.0.
Mar 6, 2012
b0d96ce
Actually merge redis options
Mar 6, 2012
a4dbd30
Use module pattern. Do not export buildPrivatePub function unnecessar…
vollnhals Apr 6, 2012
2790cc8
only load faye.js if Faye object is not present
vollnhals Apr 6, 2012
21f352d
only subscribe once to a channel
vollnhals Apr 20, 2012
105016d
Merge branch 'master' of https://github.com/ryanb/private_pub
vollnhals Aug 22, 2012
8e6da99
merge zlu master
vollnhals Aug 22, 2012
08b1345
do not load private_pub_redis.yml in rails
vollnhals Aug 22, 2012
28931ca
Allow configuration of server side faye server url
vollnhals Oct 31, 2012
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ It's not necessary to include faye.js since that will be handled automatically f

## Serving Faye over HTTPS (with Thin)

To server Faye over HTTPS you could create a thin configuration file `config/private_pub_thin.yml` similar to the following:
To serve Faye over HTTPS you could create a thin configuration file `config/private_pub_thin.yml` similar to the following:

```yaml
---
Expand All @@ -63,6 +63,21 @@ Finally start up Thin from the project root.
thin -C config/private_pub_thin.yml start
```

## Serving Faye with Redis engine

To serve Faye with Redis engine, you should create `config/private_pub_redis.yml`

```yaml
production:
host: redis_host
port: redis_port
password: redis_password
database: redis_database
namespace: '/namespace'
```

Note: database and namespace are optional.

## Usage

Use the `subscribe_to` helper method on any page to subscribe to a channel.
Expand Down
30 changes: 17 additions & 13 deletions app/assets/javascripts/private_pub.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
function buildPrivatePub(doc) {
var PrivatePub = (function (doc) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, the buildPrivatePub function should not be exposed.

var self = {
connecting: false,
fayeClient: null,
Expand All @@ -13,11 +13,15 @@ function buildPrivatePub(doc) {
self.fayeCallbacks.push(callback);
if (self.subscriptions.server && !self.connecting) {
self.connecting = true;
var script = doc.createElement("script");
script.type = "text/javascript";
script.src = self.subscriptions.server + ".js";
script.onload = self.connectToFaye;
doc.documentElement.appendChild(script);
if (typeof Faye === 'undefined') {
var script = doc.createElement("script");
script.type = "text/javascript";
script.src = self.subscriptions.server + ".js";
script.onload = self.connectToFaye;
doc.documentElement.appendChild(script);
} else {
self.connectToFaye();
}
}
}
},
Expand Down Expand Up @@ -47,10 +51,12 @@ function buildPrivatePub(doc) {
if (!self.subscriptions.server) {
self.subscriptions.server = options.server;
}
self.subscriptions[options.channel] = options;
self.faye(function(faye) {
faye.subscribe(options.channel, self.handleResponse);
});
if (!self.subscriptions[options.channel]) {
self.subscriptions[options.channel] = options;
self.faye(function(faye) {
faye.subscribe(options.channel, self.handleResponse);
});
}
},

handleResponse: function(message) {
Expand All @@ -67,6 +73,4 @@ function buildPrivatePub(doc) {
}
};
return self;
}

var PrivatePub = buildPrivatePub(document);
}(document));
12 changes: 11 additions & 1 deletion lib/generators/private_pub/templates/private_pub.ru
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,18 @@ require "bundler/setup"
require "yaml"
require "faye"
require "private_pub"
require "thin"

Faye::WebSocket.load_adapter('thin')

PrivatePub.load_config(File.expand_path("../config/private_pub.yml", __FILE__), ENV["RAILS_ENV"] || "development")
run PrivatePub.faye_app
Faye::WebSocket.load_adapter(PrivatePub.config[:adapter])

path = File.expand_path("../config/private_pub_redis.yml", __FILE__)
options = {}
if File.exist?(path)
require 'faye/redis'
options.merge(PrivatePub.load_redis_config(path, ENV['RAILS_ENV'] || 'development'))
end

run PrivatePub.faye_app(options)
3 changes: 3 additions & 0 deletions lib/generators/private_pub/templates/private_pub.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
development:
adapter: thin
server: "http://localhost:9292/faye"
secret_token: "secret"
test:
adapter: thin
server: "http://localhost:9292/faye"
secret_token: "secret"
production:
adapter: thin
server: "http://example.com/faye"
secret_token: "<%= defined?(SecureRandom) ? SecureRandom.hex(32) : ActiveSupport::SecureRandom.hex(32) %>"
signature_expiration: 3600 # one hour
24 changes: 18 additions & 6 deletions lib/private_pub.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
require "digest/sha1"
require "net/http"
require "net/https"
require "yajl/json_gem"

require "private_pub/faye_extension"
require "private_pub/engine" if defined? Rails
Expand All @@ -10,19 +11,30 @@ class Error < StandardError; end

class << self
attr_reader :config
attr_reader :default_options

# Resets the configuration to the default (empty hash)
# Resets the configuration and options to the default
# configuration defaults to empty hash
def reset_config
@config = {}
@default_options = {:mount => "/faye", :timeout => 60, :extensions => [FayeExtension.new]}
end

# Loads the configuration from a given YAML file and environment (such as production)
# Loads the configuration from a given YAML file and environment (such as production)
def load_config(filename, environment)
yaml = YAML.load_file(filename)[environment.to_s]
raise ArgumentError, "The #{environment} environment does not exist in #{filename}" if yaml.nil?
yaml.each { |k, v| config[k.to_sym] = v }
end

# Loads the options from a given YAML file and environment (such as production)
def load_redis_config(filename, environment)
yaml = YAML.load_file(filename)[environment.to_s]
options = {:engine => {:type => Faye::Redis}}
yaml.each {|k, v| options[:engine][k.to_sym] = v}
options
end

# Publish the given data to a specific channel. This ends up sending
# a Net::HTTP POST request to the Faye server.
def publish_to(channel, data)
Expand All @@ -31,8 +43,9 @@ def publish_to(channel, data)

# Sends the given message hash to the Faye server using Net::HTTP.
def publish_message(message)
raise Error, "No server specified, ensure private_pub.yml was loaded properly." unless config[:server]
url = URI.parse(config[:server])
server = config[:server_server] || config[:server]
raise Error, "No server specified, ensure private_pub.yml was loaded properly." unless server
url = URI.parse(server)

form = Net::HTTP::Post.new(url.path.empty? ? '/' : url.path)
form.set_form_data(:message => message.to_json)
Expand Down Expand Up @@ -69,8 +82,7 @@ def signature_expired?(timestamp)
# Returns the Faye Rack application.
# Any options given are passed to the Faye::RackAdapter.
def faye_app(options = {})
options = {:mount => "/faye", :timeout => 45, :extensions => [FayeExtension.new]}.merge(options)
Faye::RackAdapter.new(options)
Faye::RackAdapter.new(@default_options.merge!(options))
end
end

Expand Down
2 changes: 1 addition & 1 deletion lib/private_pub/view_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def publish_to(channel, data = nil, &block)
def subscribe_to(channel)
subscription = PrivatePub.subscription(:channel => channel)
content_tag "script", :type => "text/javascript" do
raw("PrivatePub.sign(#{subscription.to_json});")
raw("if (typeof PrivatePub != 'undefined') { PrivatePub.sign(#{subscription.to_json}) }")
end
end
end
Expand Down
3 changes: 2 additions & 1 deletion private_pub.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ Gem::Specification.new do |s|
s.files = Dir["{app,lib,spec}/**/*", "[A-Z]*", "init.rb"] - ["Gemfile.lock"]
s.require_path = "lib"

s.add_dependency 'faye'
s.add_dependency 'faye', '>= 0.8.0'
s.add_dependency 'faye-redis'

s.add_development_dependency 'rake'
s.add_development_dependency 'rspec', '~> 2.8.0'
Expand Down
2 changes: 2 additions & 0 deletions spec/fixtures/private_pub.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
development:
adapter: thin
server: http://dev.local:9292/faye
secret_token: DEVELOPMENT_SECRET_TOKEN
signature_expiration: 600
production:
adapter: thin
server: http://example.com/faye
secret_token: PRODUCTION_SECRET_TOKEN
signature_expiration: 600
6 changes: 6 additions & 0 deletions spec/fixtures/private_pub_redis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
test:
host: redis_host
port: redis_port
password: redis_password
database: redis_database
namespace: '/namespace'
34 changes: 34 additions & 0 deletions spec/private_pub_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,40 @@
PrivatePub.config[:server].should eq("http://example.com/faye")
PrivatePub.config[:secret_token].should eq("PRODUCTION_SECRET_TOKEN")
PrivatePub.config[:signature_expiration].should eq(600)
PrivatePub.config[:adapter].should eq('thin')
end

context "when redis config exists" do
before do
@options = PrivatePub.load_redis_config("spec/fixtures/private_pub_redis.yml", "test")
end

it "passes redis config to faye engine options" do
@options[:engine][:type].should eq Faye::Redis
@options[:engine][:host].should eq 'redis_host'
@options[:engine][:port].should eq 'redis_port'
@options[:engine][:password].should eq 'redis_password'
@options[:engine][:database].should eq 'redis_database'
@options[:engine][:namespace].should eq '/namespace'
end

it "should pass redis config and default options to faye" do
Faye::RackAdapter.should_receive(:new) do |options|
options[:engine].should eq @options[:engine]
options[:mount].should eq '/faye'
end
PrivatePub.faye_app(@options)
end
end

context "when redis config does not exist" do
it "should not have :engine inside of options hash" do
PrivatePub.default_options.should_not include :engine
end

it "should have mount point" do
PrivatePub.default_options[:mount].should eq '/faye'
end
end

it "raises an exception if an invalid environment is passed to load_config" do
Expand Down
1 change: 1 addition & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require 'bundler/setup'
require 'json'
require 'faye'
require 'faye/redis'
Bundler.require(:default)

RSpec.configure do |config|
Expand Down