Library / SDK
pusher/pusher-http-ruby avatar
pusher/pusher-http-ruby

pusher-http-ruby is a thin, well documented client for the Pusher Channels HTTP API

Ruby library for Pusher Channels HTTP API

668 stars130 forksRubyMIT

At a glance

What is it?
The pusher gem wraps the Pusher Channels HTTP API in a Ruby interface that covers one client construction, batched and asynchronous event publishing, channel introspection and proxy settings, with TLS on by default. It targets Ruby 3.1 and later, and it is MIT licensed.
Who is it for?
pusher-http-ruby is the gem to use when a Rails or Ruby service has to publish realtime events through Pusher Channels and you would rather not hand-roll request signing, batching and retry behaviour against the HTTP API yourself.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 78 days ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One constructor takes the app id, key, secret and cluster

The gem is a Ruby interface to the Pusher Channels HTTP API, and its configuration surface is deliberately small. Installing it is a Gemfile entry and a bundle install:

``` ruby gem 'pusher'

code

or a direct gem install:

bash gem install pusher

code

The client itself is constructed with the credentials the dashboard gives you:

ruby 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 ) ```

Two of those arguments have behaviour worth internalising. The cluster value sets the host to api-<cluster>.pusher.com, so the cluster is really a routing instruction rather than a label. The use_tls value is optional and defaults to true, and it sets both the scheme and the port, with a custom port taking precedence over it.

A custom host can be passed instead, and the precedence rule is explicit: if you pass both host and cluster, the host wins and the cluster is ignored. That ordering is the kind of detail that produces a confusing production incident if you configure a cluster for one environment and a host for another and never notice which one won.

The supported platform list is short: Ruby 3.1 or greater.

PUSHER_URL and class level configuration remove credential juggling

The second construction path reads the configuration from the environment, which is the sane default for anything deployed:

``` ruby pusher = Pusher::Client.from_env

code

The variable is expected in the form http://KEY:SECRET@HOST/apps/APP_ID, and on Heroku it is already set for you. That format is worth writing down, because it is a URL that carries the secret in it, and a URL ends up in logs, error reports and process listings far more often than a dedicated secret variable does.

The same credentials can be set globally on the Pusher class instead of per client:

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

code

Global configuration is populated automatically from PUSHER_URL when that variable exists, so in practice you rarely write those four assignments yourself in a deployed environment. They matter for local development and for tests, where setting the class attributes once is less noise than passing a client into every call site.

One more transport-level setting belongs here. If requests have to go through an HTTP proxy, it is configured on the class:

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

That assignment exists because corporate networks and egress-filtered environments are the usual reason a library that otherwise just does HTTPS starts failing with connection errors that say nothing about the cause.

Triggering covers one channel, ten channels, and batches of ten events

Publishing an event is the core operation, and the API shape is a single method that grows with your use case. A single channel takes a name, an event name and a data payload:

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

code

The array form sends the same event to several channels in one API call, and there is a limit of ten channels per call.

An optional fourth argument carries extra API parameters, and the documented use is excluding a single connection from receiving the event, which is how you avoid echoing a change back to the client that caused it:

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

code

Batching sends several events in a single request:

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

The batch limit is ten events per call on multi-tenant clusters, which is a lower ceiling than most people expect and the reason trigger_batch exists as a separate method rather than as a flag.

One compatibility note: the older publisher syntax, Pusher['a_channel'].trigger('an_event', :some => 'data'), still works, and most examples and documentation you find online will show it. It has been replaced by pusher.trigger, which supports one or multiple channels.

Errors collapse to one rescue, logging to one assignment

The error handling model is simple enough to state in a sentence. Handle errors by rescuing Pusher::Error, and all errors are descendants of that class: Pusher::AuthenticationError, Pusher::HTTPError and Pusher::Error itself.

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

code

That inheritance is the useful part. A single rescue clause catches a rejected key, a failed HTTP status and a transport problem, so you do not have to enumerate failure modes to keep a bad credential from killing a background job.

Logging works the same way. Errors are logged to Pusher.logger, which by default logs at info level to STDOUT using the Logger from the standard library, and any logger can be assigned:

ruby Pusher.logger = Rails.logger ```

Swapping in Rails.logger is the difference between shipping events whose failures land in your application's log stream and shipping events whose failures disappear into standard output that nothing collects. If you deploy on a platform where stdout is captured but your logger writes elsewhere, that one line decides whether you will ever see a publish failure.

Async methods exist for the event loop and the job queue

The library offers asynchronous variants of the main calls: pusher.get_async, pusher.post_async and pusher.trigger_async, each matching the interface of its non-async counterpart.

The documentation gives two reasons to reach for them. In a web application where the response from the Channels HTTP API is not used but you want to avoid a blocking call in the request-response cycle, and in an application running in an event loop where you need to avoid blocking the reactor.

Asynchronous calls are supported either by using an event loop, with EventMachine preferred, or via a thread. The EventMachine route needs the em-http-request gem added to the Gemfile, and the repository ships an example, examples/async_message.rb, alongside a presence_channels directory under examples/.

The third option is not part of the library at all, and the documentation recommends it when you are sending a large number of events: run the calls through a job queue. That is the right answer for bulk publishing, where a trigger per record inside a request would tie the latency of your HTTP response to the latency of the Pusher API.

Note that the async methods are about not blocking your thread, not about durability. If a queued async call fails, the error handling rules still apply.

Reading channel state back through three convenience methods

The gem is not only for publishing. It exposes the read side of the Channels HTTP API through three methods, and the documentation shows the response shape for each endpoint.

pusher.channel_info takes a channel name and an options hash, and returns a hash describing the state of the channel, with an info argument naming the attributes you want, such as user_count and subscription_count. pusher.channel_users takes a presence channel name and returns the list of users subscribed to it, which is limited to Presence Channels. pusher.channels takes an options hash, where filter_by_prefix can restrict the result to channels with a prefix such as presence-, and returns a hash of occupied channels with optional attributes.

The prefix filter is what makes the third method worth having. Listing every occupied channel in an app with heavy traffic returns a large payload, and filtering by the presence- prefix is how you get the subset that actually represents connected users.

These three methods exist because the underlying API returns JSON documents and the gem's job is to turn them into Ruby hashes, which is a small service but one you would otherwise write yourself for every call site.

TLS is on by default, and there is an explicit way to switch it off

Transport defaults are documented precisely, which is unusual and welcome. API requests are made over HTTPS by default, and HTTP can be used by setting use_tls to false. Issuing that command resets the port value if it was previously specified, so the two settings are not independent.

``` ruby Pusher.use_tls = false

code

Certificate verification is on as well. As of version 0.12, SSL certificates are verified when using the synchronous http client, and the gem exposes the switch that disables it:

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

It is worth being blunt about that line. It exists for environments where certificate verification cannot be satisfied, and turning it off removes the protection against an intercepted API call carrying your channel secret. The scope matters too: it applies to the synchronous client, so code that uses the async paths has separate transport behaviour.

The maintenance picture is calm. The gem is MIT licensed, the recent releases are 2.0.5 in March 2026, 2.1.0 in April and 2.1.1 in May, and the last push to the repository was on 2026-08-05. The tree is a conventional gem layout with lib, spec, examples, a Gemfile, a Rakefile and pusher.gemspec, plus a CHANGELOG.md that is where you look before a version bump.

Editorial conclusion

pusher-http-ruby is the gem to use when a Rails or Ruby service has to publish realtime events through Pusher Channels and you would rather not hand-roll request signing, batching and retry behaviour against the HTTP API yourself. It is the wrong choice if you need to avoid the Pusher service itself, since the credential set, the cluster routing and the environment variable format are all specific to that platform, and the 2.x line targets Ruby 3.1 or greater, so an older runtime is out of scope. Verify first that your cluster value resolves to the host you expect, since host and cluster are mutually exclusive, and decide in advance how you will handle the deprecated publisher syntax still shown in most examples, before you copy one into a new codebase.

Frequently asked questions

How do I install the pusher gem?

Add gem 'pusher' to your Gemfile and run bundle install, or install it directly with gem install pusher. The gem supports Ruby 3.1 or greater.

What does the cluster option do in Pusher::Client.new?

It sets the host to api-<cluster>.pusher.com. If you pass both host and cluster, the host takes precedence and the cluster is ignored, and use_tls defaults to true while setting the scheme and the port.

How do I configure the client without hardcoding credentials?

Use Pusher::Client.from_env, which reads the PUSHER_URL environment variable in the form http://KEY:SECRET@HOST/apps/APP_ID. Global configuration on the Pusher class is populated from the same variable when it exists.

How many channels or events can I send in one call?

A trigger call can target one or more channels, limited to 10 channels per API call. trigger_batch sends multiple events in a single request, with a maximum of 10 events per call on multi-tenant clusters.

How do I publish events without blocking my request?

Use the async methods, pusher.get_async, pusher.post_async and pusher.trigger_async, which work with an event loop such as EventMachine, which is preferred, or via a thread. For a large number of events, the documentation recommends a job queue instead.

How do I disable SSL certificate verification in the pusher gem?

Set Pusher.default_client.sync_http_client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE. Certificate verification has been on by default since version 0.12 for the synchronous HTTP client.

Official sources

  1. License: MIT
  2. Project website
  3. pusher/pusher-http-ruby on GitHub
  4. README
  5. Releases

Was this useful?