Giter VIP home page Giter VIP logo

pusher-http-ruby's Introduction

Gem for Pusher Channels

This Gem provides a Ruby interface to the Pusher HTTP API for Pusher Channels.

Build Status Gem Gem

Supported Platforms

  • Ruby - supports Ruby 2.6 or greater.

Installation and Configuration

Add pusher to your Gemfile, and then run bundle install

gem 'pusher'

or install via gem

gem install pusher

After registering at Pusher, configure your Channels app with the security credentials.

Instantiating a Pusher Channels client

Creating a new Pusher Channels client can be done as follows.

require 'pusher'

pusher = Pusher::Client.new(
  app_id: 'your-app-id',
  key: 'your-app-key',
  secret: 'your-app-secret',
  cluster: 'your-app-cluster',
  use_tls: true
)

The cluster value will set the host to api-<cluster>.pusher.com. The use_tls value is optional and defaults to true. It will set the scheme and port. A custom port value takes precendence over use_tls.

If you want to set a custom host value for your client then you can do so when instantiating a Pusher Channels client like so:

require 'pusher'

pusher = Pusher::Client.new(
  app_id: 'your-app-id',
  key: 'your-app-key',
  secret: 'your-app-secret',
  host: 'your-app-host'
)

If you pass both host and cluster options, the host will take precendence and cluster will be ignored.

Finally, if you have the configuration set in an PUSHER_URL environment variable, you can use:

pusher = Pusher::Client.from_env

Global configuration

The library can also be configured globally on the Pusher class.

Pusher.app_id = 'your-app-id'
Pusher.key = 'your-app-key'
Pusher.secret = 'your-app-secret'
Pusher.cluster = 'your-app-cluster'

Global configuration will automatically be set from the PUSHER_URL environment variable if it exists. This should be in the form http://KEY:SECRET@HOST/apps/APP_ID. On Heroku this environment variable will already be set.

If you need to make requests via a HTTP proxy then it can be configured

Pusher.http_proxy = 'http://(user):(password)@(host):(port)'

By default API requests are made over HTTPS. HTTP can be used by setting use_tls to false. Issuing this command is going to reset port value if it was previously specified.

Pusher.use_tls = false

As of version 0.12, SSL certificates are verified when using the synchronous http client. If you need to disable this behaviour for any reason use:

Pusher.default_client.sync_http_client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE

Interacting with the Channels HTTP API

The pusher gem contains a number of helpers for interacting with the API. As a general rule, the library adheres to a set of conventions that we have aimed to make universal.

Handling errors

Handle errors by rescuing Pusher::Error (all errors are descendants of this error)

begin
  pusher.trigger('a_channel', 'an_event', :some => 'data')
rescue Pusher::Error => e
  # (Pusher::AuthenticationError, Pusher::HTTPError, or Pusher::Error)
end

Logging

Errors are logged to Pusher.logger. It will by default log at info level to STDOUT using Logger from the standard library, however you can assign any logger:

Pusher.logger = Rails.logger

Publishing events

An event can be published to one or more channels (limited to 10) in one API call:

pusher.trigger('channel', 'event', foo: 'bar')
pusher.trigger(['channel_1', 'channel_2'], 'event_name', foo: 'bar')

An optional fourth argument may be used to send additional parameters to the API, for example to exclude a single connection from receiving the event.

pusher.trigger('channel', 'event', {foo: 'bar'}, {socket_id: '123.456'})

Batches

It's also possible to send multiple events with a single API call (max 10 events per call on multi-tenant clusters):

pusher.trigger_batch([
  {channel: 'channel_1', name: 'event_name', data: { foo: 'bar' }},
  {channel: 'channel_1', name: 'event_name', data: { hello: 'world' }}
])

Deprecated publisher API

Most examples and documentation will refer to the following syntax for triggering an event:

Pusher['a_channel'].trigger('an_event', :some => 'data')

This will continue to work, but has been replaced by pusher.trigger which supports one or multiple channels.

Getting information about the channels in your Pusher Channels app

This gem provides methods for accessing information from the Channels HTTP API. The documentation also shows an example of the responses from each of the API endpoints.

The following methods are provided by the gem.

  • pusher.channel_info('channel_name', {info:"user_count,subscription_count"}) returns a hash describing the state of the channel(docs).

  • pusher.channel_users('presence-channel_name') returns a list of all the users subscribed to the channel (only for Presence Channels) (docs).

  • pusher.channels({filter_by_prefix: 'presence-', info: 'user_count'}) returns a hash of occupied channels (optionally filtered by prefix, f.i. presence-), and optionally attributes for these channels (docs).

Asynchronous requests

There are two main reasons for using the _async methods:

  • In a web application where the response from the Channels HTTP API is not used, but you'd like to avoid a blocking call in the request-response cycle
  • Your application is running in an event loop and you need to avoid blocking the reactor

Asynchronous calls are supported either by using an event loop (eventmachine, preferred), or via a thread.

The following methods are available (in each case the calling interface matches the non-async version):

  • pusher.get_async
  • pusher.post_async
  • pusher.trigger_async

It is of course also possible to make calls to the Channels HTTP API via a job queue. This approach is recommended if you're sending a large number of events.

With EventMachine

  • Add the em-http-request gem to your Gemfile (it's not a gem dependency).
  • Run the EventMachine reactor (either using EM.run or by running inside an evented server such as Thin).

The _async methods return an EM::Deferrable which you can bind callbacks to:

pusher.get_async("/channels").callback { |response|
  # use reponse[:channels]
}.errback { |error|
  # error is an instance of Pusher::Error
}

A HTTP error or an error response from Channels will cause the errback to be called with an appropriate error object.

Without EventMachine

If the EventMachine reactor is not running, async requests will be made using threads (managed by the httpclient gem).

An HTTPClient::Connection object is returned immediately which can be interrogated to discover the status of the request. The usual response checking and processing is not done when the request completes, and frankly this method is most useful when you're not interested in waiting for the response.

Authenticating subscription requests

It's possible to use the gem to authenticate subscription requests to private or presence channels. The authenticate method is available on a channel object for this purpose and returns a JSON object that can be returned to the client that made the request. More information on this authentication scheme can be found in the docs on https://pusher.com/docs/channels/server_api/authenticating-users

Private channels

pusher.authenticate('private-my_channel', params[:socket_id])

Presence channels

These work in a very similar way, but require a unique identifier for the user being authenticated, and optionally some attributes that are provided to clients via presence events:

pusher.authenticate('presence-my_channel', params[:socket_id],
  user_id: 'user_id',
  user_info: {} # optional
)

Receiving WebHooks

A WebHook object may be created to validate received WebHooks against your app credentials, and to extract events. It should be created with the Rack::Request object (available as request in Rails controllers or Sinatra handlers for example).

webhook = pusher.webhook(request)
if webhook.valid?
  webhook.events.each do |event|
    case event["name"]
    when 'channel_occupied'
      puts "Channel occupied: #{event["channel"]}"
    when 'channel_vacated'
      puts "Channel vacated: #{event["channel"]}"
    end
  end
  render text: 'ok'
else
  render text: 'invalid', status: 401
end

End-to-end encryption

This library supports end-to-end encrypted channels. This means that only you and your connected clients will be able to read your messages. Pusher cannot decrypt them. You can enable this feature by following these steps:

  1. Add the rbnacl gem to your Gemfile (it's not a gem dependency).

  2. Install Libsodium, which we rely on to do the heavy lifting. Follow the installation instructions for your platform.

  3. Encrypted channel subscriptions must be authenticated in the exact same way as private channels. You should therefore create an authentication endpoint on your server.

  4. Next, generate your 32 byte master encryption key, encode it as base64 and pass it to the Pusher constructor.

    This is secret and you should never share this with anyone. Not even Pusher.

    openssl rand -base64 32
    pusher = new Pusher::Client.new({
      app_id: 'your-app-id',
      key: 'your-app-key',
      secret: 'your-app-secret',
      cluster: 'your-app-cluster',
      use_tls: true
      encryption_master_key_base64: '<KEY GENERATED BY PREVIOUS COMMAND>',
    });
  5. Channels where you wish to use end-to-end encryption should be prefixed with private-encrypted-.

  6. Subscribe to these channels in your client, and you're done! You can verify it is working by checking out the debug console on the https://dashboard.pusher.com/ and seeing the scrambled ciphertext.

Important note: This will not encrypt messages on channels that are not prefixed by private-encrypted-.

Limitation: you cannot trigger a single event on multiple channels in a call to trigger, e.g.

pusher.trigger(
  ['channel-1', 'private-encrypted-channel-2'],
  'test_event',
  { message: 'hello world' },
)

Rationale: the methods in this library map directly to individual Channels HTTP API requests. If we allowed triggering a single event on multiple channels (some encrypted, some unencrypted), then it would require two API requests: one where the event is encrypted to the encrypted channels, and one where the event is unencrypted for unencrypted channels.

pusher-http-ruby's People

Contributors

benpickles avatar benross92 avatar benw-pusher avatar callum-oakley avatar danielwaterworth avatar fujimura avatar hamchapman avatar hovsater avatar ismasan avatar jackfranklin avatar jameshfisher avatar joshk avatar jpatel531 avatar markburns avatar maryrosecook avatar mdpye avatar miksago avatar mloughran avatar olly avatar pl avatar pusher-ci avatar samuelyallop-pusher avatar sfcgeorge avatar timherby avatar topliceanu avatar toshi3221 avatar vivangkumar avatar wildfalcon avatar willsewell avatar zimbatm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pusher-http-ruby's Issues

Rails 3 compatibility

My issue is actually in relation to session[:session_id] so quite likely not a pusher gem problem. But was wondering why you don't have any Rails 3 demo apps.

Add specific usage-focussed functions

The Pusher REST API (https://pusher.com/docs/rest_api) is simple enough that it makes sense to create specific usage-focussed functions for interacting with it.

For example, we could add the following functions:

getOccupiedChannelInfo(info = nil, prefix = nil)

getChannelInfo(channel_name, info = nil)

getPresenceMembers(channel_name)

They would essentially only be implemented as utility functions that form the path for you and populate the params, but that still seems like a good idea.

Pusher::HTTPError: execution expired (HTTPClient::ConnectTimeoutError)

Having problem with Pusher Pusher::HTTPError: execution expired (HTTPClient::ConnectTimeoutError)

i also increased the timeout, yet no change.
this happens in Rails 4.2.4 console, controller and Delayed::Job

what could be wrong?

2.2.2 :009 > Pusher.timeout=360000
=> 360000
2.2.2 :010 > Pusher.trigger('test_channel', 'my_event', {message: 'hello world'})
Pusher::HTTPError: execution expired (HTTPClient::ConnectTimeoutError)
from /home/vg/.rvm/gems/ruby-2.2.2/gems/pusher-0.14.5/lib/pusher/request.rb:33:in rescue in send_sync' from /home/vg/.rvm/gems/ruby-2.2.2/gems/pusher-0.14.5/lib/pusher/request.rb:27:insend_sync'
from /home/vg/.rvm/gems/ruby-2.2.2/gems/pusher-0.14.5/lib/pusher/resource.rb:18:in post' from /home/vg/.rvm/gems/ruby-2.2.2/gems/pusher-0.14.5/lib/pusher/client.rb:144:inpost'
from /home/vg/.rvm/gems/ruby-2.2.2/gems/pusher-0.14.5/lib/pusher/client.rb:228:in trigger' from (irb):10 from /home/vg/.rvm/gems/ruby-2.2.2/gems/railties-4.2.4/lib/rails/commands/console.rb:110:instart'
from /home/vg/.rvm/gems/ruby-2.2.2/gems/railties-4.2.4/lib/rails/commands/console.rb:9:in start' from /home/vg/.rvm/gems/ruby-2.2.2/gems/railties-4.2.4/lib/rails/commands/commands_tasks.rb:68:inconsole'
from /home/vg/.rvm/gems/ruby-2.2.2/gems/railties-4.2.4/lib/rails/commands/commands_tasks.rb:39:in run_command!' from /home/vg/.rvm/gems/ruby-2.2.2/gems/railties-4.2.4/lib/rails/commands.rb:17:in<top (required)>'
from /home/vg/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.4/lib/active_support/dependencies.rb:274:in require' from /home/vg/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.4/lib/active_support/dependencies.rb:274:inblock in require'
from /home/vg/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.4/lib/active_support/dependencies.rb:240:in load_dependency' from /home/vg/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.4/lib/active_support/dependencies.rb:274:inrequire'
from /home/vg/tongs/last/uae/foodiac-ae-api/bin/rails:8:in <top (required)>' from /home/vg/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.4/lib/active_support/dependencies.rb:268:inload'
from /home/loista/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.4/lib/active_support/dependencies.rb:268:in block in load' from /home/loista/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.4/lib/active_support/dependencies.rb:240:inload_dependency'
from /home/vg/.rvm/gems/ruby-2.2.2/gems/activesupport-4.2.4/lib/active_support/dependencies.rb:268:in load' from /home/vg/.rvm/rubies/ruby-2.2.2/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:inrequire'
from /home/vg/.rvm/rubies/ruby-2.2.2/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in require' from -e:1:in

'2.2.2 :011 >
2.2.2 :012 >

About asynchronous listening

When doing asynchronous triggering:

Pusher['a_channel'].trigger_async('an_event', {
  :some => 'data'
}

Listening for events on the channel looks like:

var pusher  = new Pusher('<%= Pusher.key %>'); // uses your API KEY
var channel = pusher.subscribe('a_channel');

channel.bind('an_event', function(data) {
  alert('foobar');
});

Will the listening part block a typical web application by using a single thread, or will it do it asynchronously as well?

support cluster option

Allow library clients to better control the cluster they are using. Define a cluster option for the connection constructor and have it override the host option if present.

Does not work on heroku

Hello,

I have setup Pusher gem successfully in my Rails 3.2.14 app on my local machine. All works fine. But when I upload and run it on Heroku I get this:

from /app/vendor/bundle/ruby/2.0.0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:251:in block in require' 2013-11-01T16:25:04.271869+00:00 app[web.1]: /app/app/models/signature.rb:1:in<top (required)>': Signature is not a class (TypeError)
2013-11-01T16:25:04.272002+00:00 app[web.1]: from /app/vendor/bundle/ruby/2.0.0/gems/railties-3.2.14/lib/rails/engine.rb:444:in block (2 levels) in eager_load!' 2013-11-01T16:25:04.272008+00:00 app[web.1]: from /app/vendor/bundle/ruby/2.0.0/gems/railties-3.2.14/lib/rails/engine.rb:443:ineach'
2013-11-01T16:25:04.271931+00:00 app[web.1]: from /app/vendor/bundle/ruby/2.0.0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:251:in require' 2013-11-01T16:25:04.272145+00:00 app[web.1]: from /app/config/environment.rb:5:in<top (required)>'

I am using a init file called pusher.rb with this content:

Pusher.app_id = 'XXX'
Pusher.key = 'XXXXXXX'
Pusher.secret = 'XXXXXXX'

What can be wrong here?

Unknown auth_key

With basic setup in rails app I tried pusher. When I try this in rails console rails c I got this error

2.2.1 :053 > Pusher.trigger('my_channel', 'my_event', {message: 'hello world'})
Pusher::Error: Bad request: Unknown auth_key
    from /Users/varun/.rvm/gems/ruby-2.2.1/gems/pusher-0.14.5/lib/pusher/request.rb:88:in `handle_response'
    from /Users/varun/.rvm/gems/ruby-2.2.1/gems/pusher-0.14.5/lib/pusher/request.rb:38:in `send_sync'
    from /Users/varun/.rvm/gems/ruby-2.2.1/gems/pusher-0.14.5/lib/pusher/resource.rb:18:in `post'
    from /Users/varun/.rvm/gems/ruby-2.2.1/gems/pusher-0.14.5/lib/pusher/client.rb:144:in `post'
    from /Users/varun/.rvm/gems/ruby-2.2.1/gems/pusher-0.14.5/lib/pusher/client.rb:228:in `trigger'
    from (irb):53
    from /Users/varun/.rvm/gems/ruby-2.2.1/gems/railties-4.2.3/lib/rails/commands/console.rb:110:in `start'
    from /Users/varun/.rvm/gems/ruby-2.2.1/gems/railties-4.2.3/lib/rails/commands/console.rb:9:in `start'
    from /Users/varun/.rvm/gems/ruby-2.2.1/gems/railties-4.2.3/lib/rails/commands/commands_tasks.rb:68:in `console'
    from /Users/varun/.rvm/gems/ruby-2.2.1/gems/railties-4.2.3/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
    from /Users/varun/.rvm/gems/ruby-2.2.1/gems/railties-4.2.3/lib/rails/commands.rb:17:in `<top (required)>'
    from /Users/varun/.rvm/gems/ruby-2.2.1/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:274:in `require'
    from /Users/varun/.rvm/gems/ruby-2.2.1/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:274:in `block in require'
    from /Users/varun/.rvm/gems/ruby-2.2.1/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:240:in `load_dependency'
    from /Users/varun/.rvm/gems/ruby-2.2.1/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:274:in `require'
    from /Users/varun/Projects/Allt/bin/rails:9:in `<top (required)>'
    from /Users/varun/.rvm/gems/ruby-2.2.1/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:268:in `load'
    from /Users/varun/.rvm/gems/ruby-2.2.1/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:268:in `block in load'
    from /Users/varun/.rvm/gems/ruby-2.2.1/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:240:in `load_dependency'
    from /Users/varun/.rvm/gems/ruby-2.2.1/gems/activesupport-4.2.3/lib/active_support/dependencies.rb:268:in `load'
    from /Users/varun/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
    from /Users/varun/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'

Validate that credentials are set before calling get, post, etc.

This happens rarely, very rarely. it does seem sporadic. This is the ruby code
Pusher.get("/channels/presence-oma.presentations.1", info: :user_count)[:user_count]
It happened once before too, back then I changed the channel name, restarted the rails app, hit reload and got the same error. Right now, I've just been idle for a long time. Yeah, I know I'm not helping much... See stacktrace:

TypeError - no implicit conversion of nil into String:
  signature (0.1.7) lib/signature.rb:173:in `signature'
  signature (0.1.7) lib/signature.rb:53:in `sign'
  pusher (0.11.3) lib/pusher/request.rb:20:in `initialize'
  pusher (0.11.3) lib/pusher/resource.rb:29:in `create_request'
  pusher (0.11.3) lib/pusher/resource.rb:9:in `get'
  pusher (0.11.3) lib/pusher/client.rb:107:in `get'
  /Users/oma/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/forwardable.rb:171:in `get'
  app/models/presentations/presentation.rb:37:in `student_count'

pusher 0.11.3
ruby 2.0.0
rails 4.0.0

Rack dependency

Right now Rack is declared as a development dependency but Pusher::WebHook uses Rack::Request here.

There are two solutions: add Rack as a dependency or (better IMO) change the if to something that just checks if the given object quacks like a Rack::Request.

What do you think?

SSL_connect returned=1 errno=0 state=SSLv3

Hi
I am getting following error. Do you know how i can fix this?

Thanks

Parameters: {"utf8"=>"โœ“", "socket_id"=>"130812.12923904", "chat_message"=>{"name"=>"ffffff", "message"=>"fffff"}, "commit"=>"Send"}
{"utf8"=>"โœ“", "socket_id"=>"130812.12923904", "chat_message"=>{"name"=>"ffffff", "message"=>"fffff"}, "commit"=>"Send", "action"=>"create", "controller"=>"chat_messages"}
Completed 500 Internal Server Error in 4675ms

OpenSSL::SSL::SSLError (SSL_connect returned=1 errno=0 state=SSLv3 read server hello A: sslv3 alert handshake failure):
app/controllers/chat_messages_controller.rb:10:in `create'

Rails 3 tutorial?

I'm looking at this, and from the documentation I can't figure out for the life of me how to get this to work in a super basic Rails 3.x app.

I'm unsure where to put the example code of:

begin
Pusher['a_channel'].trigger!('an_event', {:some => 'data'})
rescue Pusher::Error => e

(Pusher::AuthenticationError, Pusher::HTTPError, or Pusher::Error)

end

And also unsure how to retrieve the data that's been sent.

If I just have a simple scaffold of a Comment that has a string of content, how do I get it to send to Pusher and how can I retrieve it in another view?

using trigger! cause an abort trap

using ruby 1.8.7p334 whenever I try and trigger and even I get the following

Assertion failed: (data != NULL), function yajl_buf_append, file yajl_buf.c, line 91.

any ideas?

Possible docs improvement: what browser socket receives

It might be possibly good to add some examples of pushed data structures so that people could see what exactly browser receives. I expected pretty much the same thing that I've got, but I needed to test before I made sure everything's working just like that. If anyone's interested:

  <= Pusher['test'].trigger('string', 'test')
  => test

  <= Pusher['test'].trigger('hash', { :test => 'test' })
  => { test: "test" }

  <= Pusher['test'].trigger('hash', { 'test' => 'test', :test2 => test2 })
  => { test: "test", test2: "test2" }

  <= Pusher['test'].trigger('event', { :test => 0, :test_negative => -1, :test_boolean => true, :test_nil => nil })
  => { test: 0, test_boolean: true, test_negative: -1, test_nil: null }

  <= Pusher['test'].trigger('test_arrayarray', [ 0, 1, 2, 3 ])
  => [ 0, 1, 2, 3 ]

  <= Pusher['test'].trigger('mixed_array', [ 0, 'a', 2, 'c' ] )
  => [ 0, 'a', 2, 'a' ]

  <= Pusher['test'].trigger('array_of_arrays', [ ['a'], ['b'] ] )
  => [ [ 'a' ], [ 'b' ] ]

  <= Pusher['test'].trigger('array_of_hashes', [ { 'a' => 1 ], { 'b' => 2 } ] )
  => [ [ 'a': 1 ], [ 'b': 2 ] ]

Persistent connections ?

I wonder if it's possible to have a version which supports persistent connections like net-http-persistent.

For that, it would probably be better to have a connection object that is not memoized per channel but per end-point. Maybe introduce a new Pusher::Client that can be derived by different http client implementations and can be used by the Pusher::Channel. That would also avoid having inline requires in Channel#trigger.

Use Faraday Gem For Swappable HTTP Backends

I have noticed other websocket libs use the faraday gem to provide different HTTP backends. That way people can use their standard (like Typhoeus). I would be willing to work on a patch for this too if you think it is a good idea?

Error in IRB: undefined method `meta_add_field' for "":String

Hi All,

My question is the following, I'm using the pusher gem and if I follow the instructions to send a message from ruby (which I execute in irb), I get the below rendered error.

The message does get send to the pusher debugger window successfully, it's just that this error message is thrown.

Additionally, this error is thrown only when I attempt to send messages from my VPS, on my local machine all is fine.

Could you guys help me out on this one?

Thanks in advance.

Cheers,
Marcel

head :001 > require 'pusher'
=> true
head :002 > Pusher.app_id = 'APP_ID'
=> "APP_ID"
head :003 > Pusher.app_id
=> "APP_ID"
head :004 > Pusher.key = 'MY_KEY'
=> "MY_KEY"
head :005 > Pusher.secret = 'MY_SECRET'
=> "MY_SECRET"
head :006 > Pusher.trigger('my-channel', 'my-event', {:message => 'hello world'})
NoMethodError: undefined method meta_add_field' for "":String from /home/tiny/.rvm/gems/ruby-head/gems/httpclient-2.3.4.1/lib/httpclient/http.rb:236:inset_body_encoding'
from /home/tiny/.rvm/gems/ruby-head/gems/httpclient-2.3.4.1/lib/httpclient/http.rb:325:in set_headers' from /home/tiny/.rvm/gems/ruby-head/gems/httpclient-2.3.4.1/lib/httpclient.rb:1138:indo_get_header'
from /home/tiny/.rvm/gems/ruby-head/gems/httpclient-2.3.4.1/lib/httpclient.rb:1086:in do_get_block' from /home/tiny/.rvm/gems/ruby-head/gems/httpclient-2.3.4.1/lib/httpclient.rb:887:inblock in do_request'
from /home/tiny/.rvm/gems/ruby-head/gems/httpclient-2.3.4.1/lib/httpclient.rb:981:in protect_keep_alive_disconnected' from /home/tiny/.rvm/gems/ruby-head/gems/httpclient-2.3.4.1/lib/httpclient.rb:886:indo_request'
from /home/tiny/.rvm/gems/ruby-head/gems/httpclient-2.3.4.1/lib/httpclient.rb:774:in request' from /home/tiny/.rvm/gems/ruby-head/gems/pusher-0.12.0/lib/pusher/request.rb:28:insend_sync'
from /home/tiny/.rvm/gems/ruby-head/gems/pusher-0.12.0/lib/pusher/resource.rb:18:in post' from /home/tiny/.rvm/gems/ruby-head/gems/pusher-0.12.0/lib/pusher/client.rb:144:inpost'
from /home/tiny/.rvm/gems/ruby-head/gems/pusher-0.12.0/lib/pusher/client.rb:226:in trigger' from (irb):6 from /home/tiny/.rvm/rubies/ruby-head/bin/irb:15:in

'

Default timeouts for the HTTP clients

Right now it's not possible to configure the timeout defaults of the Net::HTTP clients (and possibly EM::HTTPClient).

Here are the defaults on Net::HTTP:

keep_alive_timeout = 2
# Depends on system settings. Usually 240 seconds on Linux.
open_timeout = nil
read_timeout = 60
continue_timeout = nil
ssl_timeout = nil

In the context of a webapp you usually want to lower these numbers to stay below a ~5 second threshold and then return an error message to the user if the connection or response didn't happen. The webapp usually has fast connectivity so we don't need to be so forgiving during the connection. Issues are more related to downtime or equipment failure and giving it more time won't generally help. Heroku also disconnects the customer from the webapp after 30 seconds so in that case you also want to send a meaningful reply to the customer instead of the default heroku 500 message.

I don't have the time right now to propose a patch so until them I'm going to use the following monkey-patch. If you add a setting to these defaults make sure to catch the "Net::OpenTimeout" exception in https://github.com/pusher/pusher-gem/blob/master/lib/pusher/request.rb#L40

Cheers !

require 'net/http'
module Net
  class HTTP < Protocol
    alias default_timeout_initializer initialize
    def initialize(address, port = nil)
      default_timeout_initializer(address, port)
      #@keep_alive_timeout = 2
      @open_timeout = 2
      @read_timeout = 5
      @continue_timeout = 5
      @ssl_timeout = 2
    end
  end
end

How send stdout on realtime on ruby?

This construction collect stdout and push all after end execute cmd, but I want push stdout on realtime, how?

require 'open3'
def run_cmd(cmd)
    Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
      pid = wait_thr.pid # pid of the started process.
      while stdout_line = stdout.gets
        push_msg stdout_line
      end
      while stderr_line = stderr.gets
        push_msg stderr_line
      end

      exit_status = wait_thr.value
      unless exit_status.success?
        push_msg "FAILED !!! #{cmd}"
      end
    end
end

private
def push_msg(msg, channel = 'my-channel', event = 'my-event')
    puts msg
    Pusher[channel].trigger(event, {
        message: "#{msg}"
    })
end

Remove the use of ~> in gemspec

Using ~> in gemspecs causes terrible dependency issues when another library requires a newer version of a gem.

I'm currently running into this error which I don't know how to get around

In Gemfile:
  pusher depends on
    json (~> 1.4.0)

  cucumber-rails depends on
    json (1.5.1)

Proposed solution: please change ~> to >=, that way new releases of json, crack, etc can be used.

Thanks

Pusher auth problem: "A secret is required to generate an integrity hash for cookie session data."

I'm getting this error periodically using actionpack 3.2.12. I'm not sure if it's a pusher issue or a Rails issue. The site is running with Puma so it's possibly a threadsafety issue with either library. Just wondering if it rang any bells for you before I start going down the rabbit hole:

vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_dispatch/middleware/cookies.rb:319:in `ensure_secret_secure'
vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_dispatch/middleware/cookies.rb:284:in `initialize'
vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_dispatch/middleware/cookies.rb:231:in `new'
vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_dispatch/middleware/cookies.rb:231:in `signed'
vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_dispatch/middleware/session/cookie_store.rb:53:in `block in unpacked_cookie_data'
vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_dispatch/middleware/session/abstract_store.rb:57:in `stale_session_check!'
vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_dispatch/middleware/session/cookie_store.rb:51:in `unpacked_cookie_data'
vendor/bundle/ruby/1.9.1/gems/rack-1.4.5/lib/rack/session/cookie.rb:107:in `extract_session_id'
vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_dispatch/middleware/session/abstract_store.rb:53:in `block in extract_session_id'
vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_dispatch/middleware/session/abstract_store.rb:57:in `stale_session_check!'
vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_dispatch/middleware/session/abstract_store.rb:53:in `extract_session_id'
vendor/bundle/ruby/1.9.1/gems/rack-1.4.5/lib/rack/session/abstract/id.rb:43:in `load_session_id!'
vendor/bundle/ruby/1.9.1/gems/rack-1.4.5/lib/rack/session/abstract/id.rb:32:in `[]'
vendor/bundle/ruby/1.9.1/gems/rack-1.4.5/lib/rack/session/abstract/id.rb:267:in `current_session_id'
vendor/bundle/ruby/1.9.1/gems/rack-1.4.5/lib/rack/session/abstract/id.rb:273:in `session_exists?'
vendor/bundle/ruby/1.9.1/gems/rack-1.4.5/lib/rack/session/abstract/id.rb:107:in `exists?'
vendor/bundle/ruby/1.9.1/gems/rack-1.4.5/lib/rack/session/abstract/id.rb:127:in `load_for_read!'
vendor/bundle/ruby/1.9.1/gems/rack-1.4.5/lib/rack/session/abstract/id.rb:64:in `has_key?'
vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_dispatch/middleware/flash.rb:258:in `ensure in call'
vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_dispatch/middleware/flash.rb:259:in `call'
vendor/bundle/ruby/1.9.1/gems/rack-1.4.5/lib/rack/session/abstract/id.rb:210:in `context'
vendor/bundle/ruby/1.9.1/gems/rack-1.4.5/lib/rack/session/abstract/id.rb:205:in `call'
vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_dispatch/middleware/cookies.rb:341:in `call'
vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.12/lib/active_record/query_cache.rb:64:in `call'
vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.12/lib/active_record/connection_adapters/abstract/connection_pool.rb:479:in `call'
vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
vendor/bundle/ruby/1.9.1/gems/activesupport-3.2.12/lib/active_support/callbacks.rb:405:in `_run__2745371484127828092__call__4386290537933197328__callbacks'
vendor/bundle/ruby/1.9.1/gems/activesupport-3.2.12/lib/active_support/callbacks.rb:405:in `__run_callback'
vendor/bundle/ruby/1.9.1/gems/activesupport-3.2.12/lib/active_support/callbacks.rb:385:in `_run_call_callbacks'
vendor/bundle/ruby/1.9.1/gems/activesupport-3.2.12/lib/active_support/callbacks.rb:81:in `run_callbacks'
vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_dispatch/middleware/callbacks.rb:27:in `call'
vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_dispatch/middleware/remote_ip.rb:31:in `call'
vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_dispatch/middleware/debug_exceptions.rb:16:in `call'
vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_dispatch/middleware/show_exceptions.rb:56:in `call'
vendor/bundle/ruby/1.9.1/gems/railties-3.2.12/lib/rails/rack/logger.rb:32:in `call_app'
vendor/bundle/ruby/1.9.1/gems/railties-3.2.12/lib/rails/rack/logger.rb:16:in `block in call'
vendor/bundle/ruby/1.9.1/gems/activesupport-3.2.12/lib/active_support/tagged_logging.rb:22:in `tagged'
vendor/bundle/ruby/1.9.1/gems/railties-3.2.12/lib/rails/rack/logger.rb:16:in `call'
vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_dispatch/middleware/request_id.rb:22:in `call'
vendor/bundle/ruby/1.9.1/gems/rack-1.4.5/lib/rack/methodoverride.rb:21:in `call'
vendor/bundle/ruby/1.9.1/gems/rack-1.4.5/lib/rack/runtime.rb:17:in `call'
vendor/bundle/ruby/1.9.1/gems/activesupport-3.2.12/lib/active_support/cache/strategy/local_cache.rb:72:in `call'
vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_dispatch/middleware/static.rb:62:in `call'
vendor/bundle/ruby/1.9.1/gems/rack-ssl-1.3.3/lib/rack/ssl.rb:27:in `call'
vendor/bundle/ruby/1.9.1/gems/rack-cache-1.2/lib/rack/cache/context.rb:136:in `forward'
vendor/bundle/ruby/1.9.1/gems/rack-cache-1.2/lib/rack/cache/context.rb:143:in `pass'
vendor/bundle/ruby/1.9.1/gems/rack-cache-1.2/lib/rack/cache/context.rb:155:in `invalidate'
vendor/bundle/ruby/1.9.1/gems/rack-cache-1.2/lib/rack/cache/context.rb:71:in `call!'
vendor/bundle/ruby/1.9.1/gems/rack-cache-1.2/lib/rack/cache/context.rb:51:in `call'
vendor/bundle/ruby/1.9.1/gems/railties-3.2.12/lib/rails/engine.rb:479:in `call'
vendor/bundle/ruby/1.9.1/gems/railties-3.2.12/lib/rails/application.rb:223:in `call'
vendor/bundle/ruby/1.9.1/gems/railties-3.2.12/lib/rails/railtie/configurable.rb:30:in `method_missing'
vendor/bundle/ruby/1.9.1/gems/rack-1.4.5/lib/rack/commonlogger.rb:33:in `call'
vendor/bundle/ruby/1.9.1/gems/puma-1.6.3/lib/puma/server.rb:412:in `handle_request'
vendor/bundle/ruby/1.9.1/gems/puma-1.6.3/lib/puma/server.rb:306:in `process_client'
vendor/bundle/ruby/1.9.1/gems/puma-1.6.3/lib/puma/server.rb:215:in `block in run'
vendor/bundle/ruby/1.9.1/gems/puma-1.6.3/lib/puma/thread_pool.rb:94:in `call'
vendor/bundle/ruby/1.9.1/gems/puma-1.6.3/lib/puma/thread_pool.rb:94:in `block in spawn_thread'

License missing from gemspec

RubyGems.org doesn't report a license for your gem. This is because it is not specified in the gemspec of your last release.

via e.g.

spec.license = 'MIT'
# or
spec.licenses = ['MIT', 'GPL-2']

Including a license in your gemspec is an easy way for rubygems.org and other tools to check how your gem is licensed. As you can image, scanning your repository for a LICENSE file or parsing the README, and then attempting to identify the license or licenses is much more difficult and more error prone. So, even for projects that already specify a license, including a license in your gemspec is a good practice. See, for example, how rubygems.org uses the gemspec to display the rails gem license.

There is even a License Finder gem to help companies/individuals ensure all gems they use meet their licensing needs. This tool depends on license information being available in the gemspec. This is an important enough issue that even Bundler now generates gems with a default 'MIT' license.

I hope you'll consider specifying a license in your gemspec. If not, please just close the issue with a nice message. In either case, I'll follow up. Thanks for your time!

Appendix:

If you need help choosing a license (sorry, I haven't checked your readme or looked for a license file), GitHub has created a license picker tool. Code without a license specified defaults to 'All rights reserved'-- denying others all rights to use of the code.
Here's a list of the license names I've found and their frequencies

p.s. In case you're wondering how I found you and why I made this issue, it's because I'm collecting stats on gems (I was originally looking for download data) and decided to collect license metadata,too, and make issues for gemspecs not specifying a license as a public service :). See the previous link or my blog post aobut this project for more information.

The operation is insecure.

We are using pusher in a pretty standard manner. This morning I noticed that Firefox versions 12.0 and greater will trow the following error:

The operation is insecure. On line: window.pusher = new Pusher(Inbox.Data.pusher_key)

To be honest I don't fully understand what's happening. I googled a bit and found several possible reports of the same issue but I am unaware if any of these apply to pusher:

I do know that as soon as I comment out the pusher class initialization it no longer errors out.

I looked at Firefox changelog and noticed that on version 12 there are several XSS and security patches introduced which seems to be the cause of this issue.

Also not sure if relevant but the error is not present when running the rails app locally, only on the server. We are using pusher version 0.8.5 and Rails 3.0.14

Please let me know if I can be of any assistance troubleshooting this issue.

Warnings with Ruby 2.3

When version <= 0.15.2 of the pusher gem is used under Ruby 2.3, the following warnings occur:

~/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/httpclient-2.7.0.1/lib/httpclient/session.rb:735:in `connect': Object#timeout is deprecated, use Timeout.timeout instead.
~/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/httpclient-2.7.0.1/lib/httpclient/session.rb:500:in `query': Object#timeout is deprecated, use Timeout.timeout instead.
~/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/httpclient-2.7.0.1/lib/httpclient/session.rb:788:in `parse_header': Object#timeout is deprecated, use Timeout.timeout instead.
~/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/httpclient-2.7.0.1/lib/httpclient/session.rb:868:in `read_body_length': Object#timeout is deprecated, use Timeout.timeout instead.

The warning comes from httpclient, and has already been addressed in nahi/httpclient#287

As soon as a new version of the httpclient gem is released, these warnings should disappear.

uncontrollable debugging data and no valid data

your sample data by default does not work, you have to remove ENV[] from your code to get rid of a 'app_key not found' error.

this code:

# Usage: $ PUSHER_KEY=YOURKEY ruby examples/hello_pusher.rb

$:.unshift(File.expand_path("../../lib", __FILE__))
require 'pusher-client'
require 'pp'

APP_KEY = 'cb65d0a7a72cd94adf1f' # || "YOUR_APPLICATION_KEY"

socket = PusherClient::Socket.new(APP_KEY)

# Subscribe to a channel
socket.subscribe('ticker.155')

# Bind to a channel event
socket['ticker.155'].bind('hello') do |data|
  pp data
end

socket.connect

does not product expected incremental ticker update from pusher, it produces millions of counting debugging messages.
How do I get proper ticker data?

nyc-dev1 pusher-ruby-client # ruby cryptsy.rb
D, [2014-10-18T07:01:40.362927 #10504] DEBUG -- : Binding pusher:connection_established to pusher_global_channel
D, [2014-10-18T07:01:40.363039 #10504] DEBUG -- : Binding pusher:connection_disconnected to pusher_global_channel
D, [2014-10-18T07:01:40.363085 #10504] DEBUG -- : Binding pusher:error to pusher_global_channel
D, [2014-10-18T07:01:40.363146 #10504] DEBUG -- : Binding pusher:ping to pusher_global_channel
D, [2014-10-18T07:01:40.363200 #10504] DEBUG -- : Binding hello to ticker.155
D, [2014-10-18T07:01:40.363252 #10504] DEBUG -- : Pusher : connecting : ws://ws.pusherapp.com:80/app/cb65d0a7a72cd94adf1f?client=pusher-ruby-client&version=0.6.0&protocol=6
D, [2014-10-18T07:01:40.493891 #10504] DEBUG -- : Websocket connected
W, [2014-10-18T07:01:40.494338 #10504]  WARN -- : 757: unexpected token at 'App is encrypted (SSL only)' (JSON::ParserError)
/usr/lib64/ruby/gems/2.1.0/gems/json-1.8.1/lib/json/common.rb:155:in `parse'
/usr/lib64/ruby/gems/2.1.0/gems/json-1.8.1/lib/json/common.rb:155:in `parse'
/usr/local/lib64/ruby/gems/2.1.0/gems/pusher-client-0.6.0/lib/pusher-client/socket.rb:229:in `parser'
/usr/local/lib64/ruby/gems/2.1.0/gems/pusher-client-0.6.0/lib/pusher-client/socket.rb:208:in `block in connect_internal'
/usr/local/lib64/ruby/gems/2.1.0/gems/pusher-client-0.6.0/lib/pusher-client/socket.rb:205:in `loop'
/usr/local/lib64/ruby/gems/2.1.0/gems/pusher-client-0.6.0/lib/pusher-client/socket.rb:205:in `connect_internal'
/usr/local/lib64/ruby/gems/2.1.0/gems/pusher-client-0.6.0/lib/pusher-client/socket.rb:76:in `connect'
cryptsy.rb:19:in `<main>'
W, [2014-10-18T07:01:40.494433 #10504]  WARN -- : Pusher : data attribute not valid JSON - you may wish to implement your own Pusher::Client.parser
D, [2014-10-18T07:01:40.494485 #10504] DEBUG -- : Dispatching global callbacks for
D, [2014-10-18T07:01:40.494532 #10504] DEBUG -- : No global callbacks to dispatch for
D, [2014-10-18T07:01:40.494569 #10504] DEBUG -- : Pusher : event received : channel: ; event:

yields;

D, [2014-10-18T06:42:46.704590 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.704647 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.704702 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.704750 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.704809 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.704867 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.704921 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.704981 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.705047 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.705102 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.705158 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.705221 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.705280 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.705336 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.705390 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.705461 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.705516 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.705571 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.705626 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.705681 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.705729 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.705792 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.705867 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.705935 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.705994 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.706044 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.706107 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.706161 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.706226 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.706302 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.706357 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.706412 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.706468 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.706520 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.706578 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.706644 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.706688 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.706748 #9564] DEBUG -- : end of file reached
D, [2014-10-18T06:42:46.706796 #9564] DEBUG -- : end of file reached

absolutely worthless. :(

What do you think about removing the "Using multiple Client objects" tests?

First of all, create work with this library! Really appreciate that you took the effort to support a Ruby-version of the server library. ๐Ÿ‘

While going through the tests in spec/client_spec.rb I came to wonder what the tests under "Using multiple Client objects" are actually testing. Since new instances of a Ruby class does not share state, we know that @client1 and @client2 will not override each other. Therefor I do not see much value in these tests and suggest we remove them. I'd be happy to create a pull request for it if you share the same opinion.

I may as well overlook something crucial here. If that is the case, I'd love to know more about these tests.

Thanks

Pusher.authenticate is not a method

The latest 0.15.0 says Pusher.authenticate was added and is preferred over the old Pusher['channel'].authenticate syntax however there is no authenticate method defined on the Pusher module. There is an instance method Pusher::Client#authenticate but this is not the same.

Getting a Pusher.url not configured error

If I try to use the Pusher.authenticate method for a presence channel it throws the following:

Pusher::ConfigurationError: Missing configuration: please check that Pusher.url is configured
[GEM_ROOT]/gems/pusher-0.8.1/lib/pusher.rb:100:in []' app/controllers/pusher_controller.rb:4:inauth'

This goes away once I push something to one of the other channels. In my case I have chat and as soon as I post a message then the presence channels and the authenticate method work.

Intermittent problems using with celluloid

Hi
I'm having trouble using pusher gem from a celluloid pool.

I've boiled the problematic setup down into this gem:
https://gist.github.com/lachie/65150813829df97f5d70

At times it seems to time out (longer than 5 seconds) for the first few requests. At other times it works fine for all requests.

My box has 8 cores, so the celluloid pool has 8 actors.

Firstly, am I doing something wrong?
If not:

  1. is this a bug in pusher-http-ruby or the underlying httpclient gem?
  2. if this is due to network problems, what's the recommended approach for coping with it?

Obviously the first requests for each client takes longer as it sets up the connection, up to 2.5secs when it works and when using https.

The question is whether the 5 second connection timeouts are happening because of

  1. network conditions
  2. pusher backend struggling
  3. or some genuine bug or race condition somewhere

It also makes me wonder what the behaviour will be if any of the http connections are dropped over time. Should I be building the retry behaviour?

202 response to a non-async request

Hope this is the right place to post this.

I'm using the Pusher[channel].trigger(event, message) call and when debugging, the response in the Pusher::Request.send_sync method is a 202, empty string. Obviously I'm expecting the 200 with a json string.

I am using the latest version 0.10.0. I've posted also on pusher.com for help. So fingers crossed someone may have come across this before.

It's fine in that the functionality still works, but because of it, my cucumber tests fail, as I'm using the pusher-fake gem, which rightly returns a 200 response, but still with an empty string not a valid json string.

Cheers

Method trigger_async does not work?

Hi,

I would like to know why 'trigger_async' does not work sometimes?
It seems to work fine at Heroku, but not from my development machine (MAC OS 10.9)

This works:

    Pusher[('timeline ' + self.event.name.to_s).parameterize].trigger('timeline', {
        timeline_event: pusher_object, action: action
    })

This doesn't work:

    Pusher[('timeline ' + self.event.name.to_s).parameterize].trigger_async('timeline', {
        timeline_event: pusher_object, action: action
    })

Error:

cannot load such file -- em-http

$ rvm info

ruby-1.9.3-p448:

  system:
    uname:       "Darwin -MacBook-Air.local 13.0.0 Darwin Kernel Version 13.0.0: Thu Sep 19 22:22:27 PDT 2013; root:xnu-2422.1.72~6/RELEASE_X86_64 x86_64"
    system:      "osx/10.9/x86_64"
    bash:        "/bin/bash => GNU bash, version 3.2.51(1)-release (x86_64-apple-darwin13)"
    zsh:         "/bin/zsh => zsh 5.0.2 (x86_64-apple-darwin13.0)"

  rvm:
    version:      "rvm 1.22.1 () by Wayne E. Seguin <[email protected]>, Michal Papis <[email protected]> [https://rvm.io/]"
    updated:      "5 months 27 days 5 hours 25 minutes 47 seconds ago"
    path:         "/Users/user/.rvm"

  ruby:
    interpreter:  "ruby"
    version:      "1.9.3p448"
    date:         "2013-06-27"
    platform:     "x86_64-darwin11.4.2"
    patchlevel:   "2013-06-27 revision 41675"
    full_version: "ruby 1.9.3p448 (2013-06-27 revision 41675) [x86_64-darwin11.4.2]"

Thanks in advance

Use to_json instead of MultiJSON gem

A good practice for sending out model objects via WebSockets as JSON is to simply override the as_json method of the model class. Unfortunately this does not work with Pusher, because Pusher does not call the model's to_json method. I would vote for switching to the standard to_json method instead of using the MultiJSON gem, so the mentioned best practice is supported.

I could the simply do

Pusher[pusher_channel_id].trigger!(message, my_rails_model)

and control which attributes are sent out via my_rails_model.as_json.

Auth timestamp not correct

I did try to use this gem with ruby 2.0.0 and rails4. But I always get issue:

Timestamp expired: Given timestamp (2013-09-29T08:46:33Z) not within 600s of server time (2013-09-29T08:36:32Z) (Pusher::AuthenticationError)
/Users/myname/.rvm/gems/ruby-2.0.0-p195@ror/gems/pusher-0.12.0/lib/pusher/request.rb:97:in handle_response' /Users/myname/.rvm/gems/ruby-2.0.0-p195@ror/gems/pusher-0.12.0/lib/pusher/request.rb:45:insend_sync'
/Users/myname/.rvm/gems/ruby-2.0.0-p195@ror/gems/pusher-0.12.0/lib/pusher/resource.rb:18:in post' /Users/myname/.rvm/gems/ruby-2.0.0-p195@ror/gems/pusher-0.12.0/lib/pusher/client.rb:144:inpost'

I did debug and found pusher api require auth time within 10minutes from request. But signature gem return wrong value at this line (https://github.com/pusher/pusher-gem/blob/master/lib/pusher/request.rb#L21)

Lots of Net::HTTP / Net::Protocol errors with Sidekiq (threadsafe issue?)

I have switch from Delayed::Job to Sidekiq and now I got a lot of issue from Pusher trigs, like:

  • IOError: stream closed
  • IOError: closed stream
  • NoMethodError: undefined methodclosed?' for nil:NilClass`
  • NoMethodError: undefined method+' for nil:NilClass`
  • MultiJson::DecodeError: no object read at line 1, column 1 [load.c:1042]
  • NoMethodError: private methodreadline' called for nil:NilClass`

All coming from pusher/request.rb:30:insend_sync`

One backtrace:

vendor/ruby-1.9.3/lib/ruby/1.9.1/net/protocol.rb:199:in `write'
vendor/ruby-1.9.3/lib/ruby/1.9.1/net/protocol.rb:199:in `write0'
vendor/ruby-1.9.3/lib/ruby/1.9.1/net/protocol.rb:173:in `block in write'
vendor/ruby-1.9.3/lib/ruby/1.9.1/net/protocol.rb:190:in `writing'
vendor/ruby-1.9.3/lib/ruby/1.9.1/net/protocol.rb:172:in `write'
vendor/ruby-1.9.3/lib/ruby/1.9.1/net/http.rb:1937:in `send_request_with_body'
vendor/ruby-1.9.3/lib/ruby/1.9.1/net/http.rb:1919:in `exec'
vendor/ruby-1.9.3/lib/ruby/1.9.1/net/http.rb:1317:in `block in transport_request'
vendor/ruby-1.9.3/lib/ruby/1.9.1/net/http.rb:1316:in `catch'
vendor/ruby-1.9.3/lib/ruby/1.9.1/net/http.rb:1316:in `transport_request'
vendor/ruby-1.9.3/lib/ruby/1.9.1/net/http.rb:1293:in `request'
vendor/bundle/ruby/1.9.1/gems/newrelic_rpm-3.5.3.25/lib/new_relic/agent/instrumentation/net.rb:22:in `block in request_with_newrelic_trace'
vendor/bundle/ruby/1.9.1/gems/newrelic_rpm-3.5.3.25/lib/new_relic/agent/method_tracer.rb:242:in `trace_execution_scoped'
vendor/bundle/ruby/1.9.1/gems/newrelic_rpm-3.5.3.25/lib/new_relic/agent/instrumentation/net.rb:21:in `request_with_newrelic_trace'
vendor/ruby-1.9.3/lib/ruby/1.9.1/net/http.rb:1307:in `send_entity'
vendor/ruby-1.9.3/lib/ruby/1.9.1/net/http.rb:1096:in `post'
vendor/bundle/ruby/1.9.1/gems/pusher-0.11.1/lib/pusher/request.rb:30:in `send_sync'
vendor/bundle/ruby/1.9.1/gems/pusher-0.11.1/lib/pusher/resource.rb:18:in `post'
vendor/bundle/ruby/1.9.1/gems/pusher-0.11.1/lib/pusher/client.rb:134:in `post'
vendor/bundle/ruby/1.9.1/gems/pusher-0.11.1/lib/pusher/client.rb:216:in `trigger'

Do you have any idea from where it comes?
@mperham do you think it's more related to Sidekiq?

Thanks for your help!
Thibaud

Presence authorization relies on side effect of Ruby 1.8 hash to_s

I'm in the middle of writing a presence-auth method for my node.js app, and I had trouble getting it to work using this method: http://pusher.com/docs/auth_signatures.

Looking through this gem, I realise that pusher takes the channel_data hash and converts it to a string using Hash#to_s. (See here: https://github.com/pusher/pusher-gem/blob/master/lib/pusher/channel.rb#L130 )

This means, that instead of the string_to_sign looking something like:
"{:user_id=>10, :user_info=>{:name=>"Mr. Pusher"}}"

It instead looks like:
"user_id10user_infonameMr. Pusher"

This is just a side effect of how 1.8 turns hashes into strings. (And of course also relies on the ordering of the hash. ) The ramifications are:

  1. The presence auth functionality doesn't work in Ruby 1.9
  2. Writers of libraries using other languages have to imitate 1.8's strange hash-to-string side effect.

I'd like to fix it, but I realise that the corresponding hashing algorithm within pusher will need to change as well.

Can this be handled by a background worker?

I was thinking. Could the following block be handled by a background worker, i.e. Resque, Delayed Job, etc?

Pusher['a_channel'].trigger('an_event', {
  :some => 'data'
}

Whats the difference between executing the above block with .trigger_async() against using a background worker?

Presence Channel

Is the implementation to verify if there are users present on presence channel going to be available on a future version?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.