Pushlet

Pushlet is a simple, stateless HTTP API for interacting with Apple and Google’s push services for mobile devices. It’s goal is to simplify your push notifications by providing a simple SoA API that does this one thing, and does it well.

Pushlet integrates Grocer for APNS, and is designed to be thread safe.

Because it is containerized and requires no data store, it can be easily put on a hosted service like AppFog or Heroku.

Requirements

  • Ruby 1.9, JRuby 1.7, Rubinius 2.0 or later.

Installation and Configuration

First, install the gem via Rubygems:

gem install pushlet

Then, setup a config.ru with the following. Setup an HTTP Auth so that you can control access (we provide a simple helper for you that returns JSON error messages, but you can use any Rack Middleware you like):

require 'pushlet'

map '/' do
  Pushlet::API.http_basic_auth 'YOUR_USERNAME', 'YOUR_PASSWORD'
  run Pushlet::API
end

Pushlet is thread optimized, so use a threaded web server. I highly recommend using Puma, which is designed for threaded applications. You can add it by putting gem 'puma' in your Gemfile:

$ bundle exec puma

You can also use rackup:

$ bundle exec rackup -s puma

If using Heroku, setup a Procfile to make it start with Puma by default:

web: bundle exec puma -p $PORT

Apple Push Notifications (APNS)

Sending push notifications to apple is a two step process. First, you need to register the application via the register_application route:

$ curl http://127.0.0.1:9292/register_application -F "apns_p12=@/PATH/TO/YOUR/CERT.p12" -F "application_id=YOUR_APPLICATION_NAME"

Now you can send push notifications via the send_notification route, and the socket connection for that application will handle them:

$ curl http://127.0.0.1:9292/send_notification -d "device_token=YOUR_DEVICE_TOKEN&alert=YOUR+TEXT+MESSAGE&application_id=YOUR_APPLICATION_NAME"

Google Cloud Messaging (GCM)

Google does not require a stateful socket connection, because it uses HTTPS. It’s simple enough to implement the protocol that this project doesn’t add a lot of value for this, but we’ve included it for convenience.

GCM does not have a concept of a “message” field. You are given a data input that can be JSON, and you need to program your application to send a message based on which column you send. For example, if your pre-defined field is text, encode with something like Rack::Utils.escape({text: 'hello'}.to_json), and then send this way:

curl http://127.0.0.1:9292/send_notification -d "device_token=YOUR_GCM_DEVICE_KEY&gcm_api_key=YOUR_GCM_API_KEY&data=%7B%22text%22%3A%22hello%22%7D"

POST /application_feedback

Returns the feedback information from Apple. Not required for GCM.

Arguments

  • application_id - required

Example Response

{
  "response": [
    {
      "device_token": "abcd",
      "timestamp": "2012-11-27T22:24:07Z"
    },
    {
      "device_token": "efgh",
      "timestamp": "2012-11-27T22:24:07Z"
    }
  ]
}

Possible errors

{
  "error": "missing_application_id",
  "message": "an application_id is required for this call"
}

{
  "error": "application_not_found",
  "message": "no application found for the provided application_id"
}

POST /register_application

Registers the APNS application with a certificate. This will create a socket connection when the first message is sent, providing a persistent connection to the Apple push servers.

  • application_id - a unique identifier for this application. If none is provided, a UUID-based one will be generated and returned to you, and you will need to store it somewhere to use the connection.
  • apns_p12 - Apple certificate in P12 format. Either this or apns_pem are required.
  • apns_pem - Apple certificate in PEM format. Either this or apns_p12 are required.
  • apns_mode - toggles whether to use sandbox mode or not. If set to “development”, the sandbox is used. Defaults to production.
  • apns_p12_pass - password for P12. Optional.

Example Response

{
  "application_id": "id_you_supplied_or_uuid"
}

Possible errors

{
  "error": "missing_apns_certificate",
  "message": "an apns_p12 or apns_pem certificate is required for this call"
}

{
  "error": "invalid_apns_p12",
  "message": "could not process apns_p12 certificate, check that it is in p12 format and is valid"
}

POST /send_notification

Sends a message to either the GCM REST service or the APNS application socket.

  • type - “apns” or “gcm”. Required.
  • application_id - application_id provided for registered APNS application. Either this or gcm_api_key are required.
  • gcm_api_key - GCM secret key from Google. Either this or application_id are required.
  • device_token - the device push token provided by the phone for your application. Required.
  • data - the generic data JSON payload to send to either APNS or GCM.

APNS specific:

  • alert - the text to send as a popup message. Optional.
  • badge - the number to show on the menu icon. Optional.
  • sound - the application sound file to play on the phone. Optional.
  • identifier - 4-byte unique identifier for the message. Optional.

Example Response (APNS)

{
  "response": "ok"
}

Example Response (GCM)

{ "multicast_id": 108,
  "success": 1,
  "failure": 0,
  "canonical_ids": 0,
  "results": [
    { "message_id": "1:08" }
  ]
}

Possible errors

{
  "error": "missing_identifier",
  "message": "an application_id or gcm_api_key are required for this call"
}

{
  "error": "device_token_required",
  "message": "device_token is required, which is registed with the application on your phone"
}

{
  "error": "application_not_found",
  "message": "no application found for the provided application_id"
}

{
  "error": "invalid_data_json",
  "message": "data could not be converted to json: ERROR_MESSAGE_FROM_JSON_PARSER"
}

{
  "error": "invalid_data_json",
  "message": "data could not be converted to json: ERROR_MESSAGE_FROM_JSON_PARSER"
}

{
  "error": "invalid_gcm_credentials",
  "message": "the provided credentials were rejected by google servers"
}