apnotic 0.9.2 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
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