apnotic 0.9.2 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f1a10d2e906280964fd17047d5a6dbd4401f0a81
4
- data.tar.gz: 05e865f118c12f829b7232d5c2f44e5d43bcc0c0
3
+ metadata.gz: 9493fd00daf33a8bd13d087bcd119929b236372e
4
+ data.tar.gz: 68215cff5cfc93dd0aafdccf2188da4f6fe9b085
5
5
  SHA512:
6
- metadata.gz: 335531c6db288c0befc75bf91235ae2cd5387810b9410d6e8a342af89aeee0b81ab6e739a73f1762abb78aa7919876b8f1962517e96b1330b89d20a0998208d9
7
- data.tar.gz: 9b413dcd3a8aa1cabbb8d7dd544b3d72a7a1627e92fe2bd91939e2dd17d08fc14c2c129582d60c70f45ab4a22e24b837be55cb9d5916dbc667ffee08e9f62ea0
6
+ metadata.gz: 5bad7e789438d5e5710a433501dff4e41fa50633f22fe0eb9814653919b41a8ea34a84747854c17a0ccdb850e84f720cf9d31f293a79e6a5b5c82ba2b80d7b77
7
+ data.tar.gz: 54014458ff59af3703d94b00ffe61a3074c05ba962b60c8183f084a89a113d5051f50235c0d43b0e8c8c4a8db850ab504382b7dab8432940b8a8a4ea1762b0dd
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- ruby-2.3.0
1
+ ruby-2.3.1
data/README.md CHANGED
@@ -28,6 +28,10 @@ gem 'apnotic'
28
28
  ## Usage
29
29
 
30
30
  ### Standalone
31
+
32
+ #### Sync pushes
33
+ Sync pushes are blocking calls that will wait for an APNs response before proceeding.
34
+
31
35
  ```ruby
32
36
  require 'apnotic'
33
37
 
@@ -53,6 +57,42 @@ response.body # => ""
53
57
  connection.close
54
58
  ```
55
59
 
60
+ #### Async pushes
61
+ If you are sending out a considerable amount of push notifications, you may consider using async pushes to send out multiple requests in non-blocking calls. This allows to take full advantage of HTTP/2 streams.
62
+
63
+ ```ruby
64
+ require 'apnotic'
65
+
66
+ # create a persistent connection
67
+ connection = Apnotic::Connection.new(cert_path: "apns_certificate.pem", cert_pass: "pass")
68
+
69
+ # create a notification for a specific device token
70
+ token = "6c267f26b173cd9595ae2f6702b1ab560371a60e7c8a9e27419bd0fa4a42e58f"
71
+
72
+ notification = Apnotic::Notification.new(token)
73
+ notification.alert = "Notification from Apnotic!"
74
+
75
+ # prepare push
76
+ push = connection.prepare_push(notification)
77
+ push.on(:response) do |response|
78
+ # read the response
79
+ response.ok? # => true
80
+ response.status # => '200'
81
+ response.headers # => {":status"=>"200", "apns-id"=>"6f2cd350-bfad-4af0-a8bc-0d501e9e1799"}
82
+ response.body # => ""
83
+ end
84
+
85
+ # send
86
+ connection.push_async(push)
87
+
88
+ # wait for all requests to be completed
89
+ connection.join
90
+
91
+ # close the connection
92
+ connection.close
93
+ ```
94
+
95
+
56
96
  ### With Sidekiq / Rescue / ...
57
97
  A practical usage of a Sidekiq / Rescue worker probably has to:
58
98
 
@@ -93,6 +133,7 @@ end
93
133
 
94
134
  > The official [APNs Provider API documentation](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/APNsProviderAPI.html) explains how to interpret the responses given by the APNS.
95
135
 
136
+ You may also consider using async pushes instead in a Sidekiq / Rescue worker.
96
137
 
97
138
 
98
139
  ## Objects
@@ -129,10 +170,26 @@ Apnotic::Connection.development(options)
129
170
 
130
171
  Returns the path to the certificate
131
172
 
173
+ ##### Blocking calls
174
+
132
175
  * **push(notification, timeout: 30)** → **`Apnotic::Response` or `nil`**
133
176
 
134
177
  Sends a notification. Returns `nil` in case a timeout occurs.
135
178
 
179
+ ##### Non-blocking calls
180
+
181
+ * **prepare_push(notification)** → **`Apnotic::Push`**
182
+
183
+ Prepares an async push.
184
+
185
+ ```ruby
186
+ push = client.prepare_push(notification)
187
+ ```
188
+
189
+ * **push_async(push)**
190
+
191
+ Sends the push asynchronously.
192
+
136
193
 
137
194
  ### `Apnotic::ConnectionPool`
138
195
  For your convenience, a wrapper around the [Connection Pool](https://github.com/mperham/connection_pool) gem is here for you. To create a new connection pool:
@@ -172,6 +229,7 @@ These are all Accessor attributes.
172
229
  | `priority` | "
173
230
  | `topic` | "
174
231
  | `url_args` | Values for [Safari push notifications](https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/NotificationProgrammingGuideForWebsites/PushNotifications/PushNotifications.html#//apple_ref/doc/uid/TP40013225-CH3-SW12).
232
+ | `mutable_content` | Key for [UNNotificationServiceExtension](https://developer.apple.com/reference/usernotifications/unnotificationserviceextension).
175
233
 
176
234
  For example:
177
235
 
@@ -218,6 +276,29 @@ The response to a call to `connection.push`.
218
276
  Returns the body of the response in Hash format if a valid JSON was returned, otherwise just the RAW body.
219
277
 
220
278
 
279
+ ### `Apnotic::Push`
280
+ The push object to be sent in an async call.
281
+
282
+ #### Methods
283
+
284
+ * **on(event, &block)**
285
+
286
+ Allows to set a callback for the request. Available events are:
287
+
288
+ * `:response`: triggered when a response is fully received (called once).
289
+
290
+ Even if Apnotic is thread-safe, the async callbacks will be executed in a different thread, so ensure that your code in the callbacks is thread-safe.
291
+
292
+ ```ruby
293
+ push.on(:response) { |response| p response.headers }
294
+ ```
295
+
296
+ * **http2_request** → **`NetHttp2::Request`**
297
+
298
+ Returns the HTTP/2 request of the push.
299
+
300
+
301
+
221
302
  ## Getting Your APNs Certificate
222
303
 
223
304
  > These instructions come from another great gem, [apn_on_rails](https://github.com/PRX/apn_on_rails).
data/apnotic.gemspec CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency "net-http2", "~> 0.11.0"
21
+ spec.add_dependency "net-http2", "~> 0.12.0"
22
22
  spec.add_dependency "connection_pool", "~> 2.0"
23
23
 
24
24
  spec.add_development_dependency "bundler", "~> 1.3"
data/lib/apnotic.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'apnotic/connection'
2
2
  require 'apnotic/connection_pool'
3
3
  require 'apnotic/notification'
4
+ require 'apnotic/push'
4
5
  require 'apnotic/request'
5
6
  require 'apnotic/response'
6
7
  require 'apnotic/version'
@@ -17,9 +17,9 @@ module Apnotic
17
17
  end
18
18
 
19
19
  def initialize(options={})
20
- @url = options[:url] || APPLE_PRODUCTION_SERVER_URL
21
- @cert_path = options[:cert_path]
22
- @cert_pass = options[:cert_pass]
20
+ @url = options[:url] || APPLE_PRODUCTION_SERVER_URL
21
+ @cert_path = options[:cert_path]
22
+ @cert_pass = options[:cert_pass]
23
23
  @connect_timeout = options[:connect_timeout] || 30
24
24
 
25
25
  raise "Cert file not found: #{@cert_path}" unless @cert_path && (@cert_path.respond_to?(:read) || File.exist?(@cert_path))
@@ -37,10 +37,27 @@ module Apnotic
37
37
  Apnotic::Response.new(headers: response.headers, body: response.body) if response
38
38
  end
39
39
 
40
+ def push_async(push)
41
+ @client.call_async(push.http2_request)
42
+ end
43
+
44
+ def prepare_push(notification)
45
+ request = Apnotic::Request.new(notification)
46
+ http2_request = @client.prepare_request(:post, request.path,
47
+ body: request.body,
48
+ headers: request.headers
49
+ )
50
+ Apnotic::Push.new(http2_request)
51
+ end
52
+
40
53
  def close
41
54
  @client.close
42
55
  end
43
56
 
57
+ def join
58
+ @client.join
59
+ end
60
+
44
61
  private
45
62
 
46
63
  def ssl_context
@@ -5,7 +5,7 @@ module Apnotic
5
5
 
6
6
  class Notification
7
7
  attr_reader :token
8
- attr_accessor :alert, :badge, :sound, :content_available, :category, :custom_payload, :url_args
8
+ attr_accessor :alert, :badge, :sound, :content_available, :category, :custom_payload, :url_args, :mutable_content
9
9
  attr_accessor :apns_id, :expiration, :priority, :topic
10
10
 
11
11
  def initialize(token)
@@ -28,6 +28,7 @@ module Apnotic
28
28
  aps.merge!(category: category) if category
29
29
  aps.merge!('content-available' => content_available) if content_available
30
30
  aps.merge!('url-args' => url_args) if url_args
31
+ aps.merge!('mutable-content' => mutable_content) if mutable_content
31
32
 
32
33
  n = { aps: aps }
33
34
  n.merge!(custom_payload) if custom_payload
@@ -0,0 +1,38 @@
1
+ module Apnotic
2
+
3
+ class Push
4
+ attr_reader :http2_request
5
+
6
+ def initialize(http2_request)
7
+ @http2_request = http2_request
8
+ @headers = {}
9
+ @data = ''
10
+ @events = {}
11
+
12
+ listen_for_http2_events
13
+ end
14
+
15
+ def on(event, &block)
16
+ raise ArgumentError, 'on event must provide a block' unless block_given?
17
+
18
+ @events[event] ||= []
19
+ @events[event] << block
20
+ end
21
+
22
+ def emit(event, arg)
23
+ return unless @events[event]
24
+ @events[event].each { |b| b.call(arg) }
25
+ end
26
+
27
+ private
28
+
29
+ def listen_for_http2_events
30
+ @http2_request.on(:headers) { |headers| @headers.merge!(headers) }
31
+ @http2_request.on(:body_chunk) { |chunk| @data << chunk }
32
+ @http2_request.on(:close) do
33
+ response = Apnotic::Response.new(headers: @headers, body: @data)
34
+ emit(:response, response)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,3 +1,3 @@
1
1
  module Apnotic
2
- VERSION = "0.9.2"
2
+ VERSION = "0.10.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: apnotic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.2
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roberto Ostinelli
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-05-24 00:00:00.000000000 Z
11
+ date: 2016-06-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: net-http2
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.11.0
19
+ version: 0.12.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.11.0
26
+ version: 0.12.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: connection_pool
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -103,6 +103,7 @@ files:
103
103
  - lib/apnotic/connection.rb
104
104
  - lib/apnotic/connection_pool.rb
105
105
  - lib/apnotic/notification.rb
106
+ - lib/apnotic/push.rb
106
107
  - lib/apnotic/request.rb
107
108
  - lib/apnotic/response.rb
108
109
  - lib/apnotic/version.rb