Skip to content

Commit d7ccf74

Browse files
prcongithubkashif
authored andcommitted
Use faraday (#55)
* Enable Instance ID support * Bump version * Update method signatures * Fix typo * Enable fcm for lower Ruby versions * use faraday to support multi threaded applications
1 parent 8b14801 commit d7ccf74

File tree

3 files changed

+69
-161
lines changed

3 files changed

+69
-161
lines changed

fcm.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,5 @@ Gem::Specification.new do |s|
2121
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
2222
s.require_paths = ["lib"]
2323

24-
s.add_runtime_dependency('httparty', '~> 0.10', '>= 0.10.0')
24+
s.add_runtime_dependency('faraday','0.15.4')
2525
end

lib/fcm.rb

Lines changed: 65 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
require 'httparty'
1+
require 'faraday'
22
require 'cgi'
33
require 'json'
44

55
class FCM
6-
include HTTParty
7-
base_uri 'https://fcm.googleapis.com/fcm'
8-
default_timeout 30
9-
format :json
6+
BASE_URI = 'https://fcm.googleapis.com'
7+
DEFAULT_TIMEOUT = 30
8+
FORMAT = :json
109

1110
# constants
12-
GROUP_NOTIFICATION_BASE_URI = 'https://android.googleapis.com/gcm'
13-
INSTANCE_ID_API = 'https://iid.googleapis.com/iid'
11+
GROUP_NOTIFICATION_BASE_URI = 'https://android.googleapis.com'
12+
INSTANCE_ID_API = 'https://iid.googleapis.com'
1413
TOPIC_REGEX = /[a-zA-Z0-9\-_.~%]+/
1514

1615
attr_accessor :timeout, :api_key
@@ -35,38 +34,25 @@ def initialize(api_key, client_options = {})
3534
def send_notification(registration_ids, options = {})
3635
post_body = build_post_body(registration_ids, options)
3736

38-
params = {
39-
body: post_body.to_json,
40-
headers: {
41-
'Authorization' => "key=#{@api_key}",
42-
'Content-Type' => 'application/json'
43-
}
44-
}
45-
response = self.class.post('/send', params.merge(@client_options))
46-
build_response(response, registration_ids)
37+
for_uri(BASE_URI) do |connection|
38+
response = connection.post('/fcm/send', post_body.to_json)
39+
build_response(response, registration_ids)
40+
end
4741
end
4842
alias send send_notification
4943

5044
def create_notification_key(key_name, project_id, registration_ids = [])
5145
post_body = build_post_body(registration_ids, operation: 'create',
5246
notification_key_name: key_name)
5347

54-
params = {
55-
body: post_body.to_json,
56-
headers: {
57-
'Content-Type' => 'application/json',
58-
'project_id' => project_id,
59-
'Authorization' => "key=#{@api_key}"
60-
}
48+
extra_headers = {
49+
'project_id' => project_id
6150
}
6251

63-
response = nil
64-
65-
for_uri(GROUP_NOTIFICATION_BASE_URI) do
66-
response = self.class.post('/notification', params.merge(@client_options))
52+
for_uri(GROUP_NOTIFICATION_BASE_URI, extra_headers) do |connection|
53+
response = connection.post('/gcm/notification', post_body.to_json)
54+
build_response(response)
6755
end
68-
69-
build_response(response)
7056
end
7157
alias create create_notification_key
7258

@@ -75,21 +61,14 @@ def add_registration_ids(key_name, project_id, notification_key, registration_id
7561
notification_key_name: key_name,
7662
notification_key: notification_key)
7763

78-
params = {
79-
body: post_body.to_json,
80-
headers: {
81-
'Content-Type' => 'application/json',
82-
'project_id' => project_id,
83-
'Authorization' => "key=#{@api_key}"
84-
}
64+
extra_headers = {
65+
'project_id' => project_id
8566
}
8667

87-
response = nil
88-
89-
for_uri(GROUP_NOTIFICATION_BASE_URI) do
90-
response = self.class.post('/notification', params.merge(@client_options))
68+
for_uri(GROUP_NOTIFICATION_BASE_URI, extra_headers) do |connection|
69+
response = connection.post('/gcm/notification', post_body.to_json)
70+
build_response(response)
9171
end
92-
build_response(response)
9372
end
9473
alias add add_registration_ids
9574

@@ -98,42 +77,32 @@ def remove_registration_ids(key_name, project_id, notification_key, registration
9877
notification_key_name: key_name,
9978
notification_key: notification_key)
10079

101-
params = {
102-
body: post_body.to_json,
103-
headers: {
104-
'Content-Type' => 'application/json',
105-
'project_id' => project_id,
106-
'Authorization' => "key=#{@api_key}"
107-
}
80+
extra_headers = {
81+
'project_id' => project_id
10882
}
10983

110-
response = nil
111-
112-
for_uri(GROUP_NOTIFICATION_BASE_URI) do
113-
response = self.class.post('/notification', params.merge(@client_options))
84+
for_uri(GROUP_NOTIFICATION_BASE_URI, extra_headers) do |connection|
85+
response = connection.post('/gcm/notification', post_body.to_json)
86+
build_response(response)
11487
end
115-
build_response(response)
11688
end
11789
alias remove remove_registration_ids
11890

11991
def recover_notification_key(key_name, project_id)
12092
params = {
12193
query: {
12294
notification_key_name: key_name
123-
},
124-
headers: {
125-
'Content-Type' => 'application/json',
126-
'project_id' => project_id,
127-
'Authorization' => "key=#{@api_key}"
12895
}
12996
}
97+
98+
extra_headers = {
99+
'project_id' => project_id
100+
}
130101

131-
response = nil
132-
133-
for_uri(GROUP_NOTIFICATION_BASE_URI) do
134-
response = self.class.get('/notification', params.merge(@client_options))
102+
for_uri(GROUP_NOTIFICATION_BASE_URI, extra_headers) do |connection|
103+
response = connection.get('/gcm/notification', params)
104+
build_response(response)
135105
end
136-
build_response(response)
137106
end
138107

139108
def send_with_notification_key(notification_key, options = {})
@@ -142,20 +111,10 @@ def send_with_notification_key(notification_key, options = {})
142111
end
143112

144113
def topic_subscription(topic, registration_id)
145-
params = {
146-
headers: {
147-
'Authorization' => "key=#{@api_key}",
148-
'Content-Type' => 'application/json'
149-
}
150-
}
151-
152-
response = nil
153-
154-
for_uri(INSTANCE_ID_API) do
155-
response = self.class.post("/v1/#{registration_id}/rel/topics/#{topic}", params)
114+
for_uri(INSTANCE_ID_API) do |connection|
115+
response = connection.post("/iid/v1/#{registration_id}/rel/topics/#{topic}")
116+
build_response(response)
156117
end
157-
158-
build_response(response)
159118
end
160119

161120
def batch_topic_subscription(topic, registration_ids)
@@ -168,94 +127,44 @@ def batch_topic_unsubscription(topic, registration_ids)
168127

169128
def manage_topics_relationship(topic, registration_ids, action)
170129
body = { to: "/topics/#{topic}", registration_tokens: registration_ids }
171-
params = {
172-
body: body.to_json,
173-
headers: {
174-
'Authorization' => "key=#{@api_key}",
175-
'Content-Type' => 'application/json'
176-
}
177-
}
178130

179-
response = nil
180-
181-
for_uri(INSTANCE_ID_API) do
182-
response = self.class.post("/v1/:batch#{action}", params)
131+
for_uri(INSTANCE_ID_API) do |connection|
132+
response = connection.post("/iid/v1:batch#{action}", body.to_json)
133+
build_response(response)
183134
end
184-
185-
build_response(response)
186135
end
187136

188-
189-
190137
def send_to_topic(topic, options = {})
191138
if topic.gsub(TOPIC_REGEX, "").length == 0
192139
send_with_notification_key('/topics/' + topic, options)
193140
end
194141
end
195142

196143
def get_instance_id_info iid_token, options={}
197-
response = nil
198-
for_uri(INSTANCE_ID_API) do
199-
response = self.class.get('/info/'+iid_token, query: options, headers: {
200-
'Authorization' => "key=#{@api_key}",
201-
'Content-type' => 'application/json'
202-
})
144+
params = {
145+
query: options
146+
}
147+
148+
for_uri(INSTANCE_ID_API) do |connection|
149+
response = connection.get('/iid/info/'+iid_token, params)
150+
build_response(response)
203151
end
204-
build_response(response)
205152
end
206153

207154
def subscribe_instance_id_to_topic iid_token, topic_name
208-
response = nil
209-
for_uri(INSTANCE_ID_API) do
210-
response = self.class.post('/v1/'+iid_token+'/rel/topics/'+topic_name, headers: {
211-
'Authorization' => "key=#{@api_key}",
212-
'Content-type' => 'application/json'
213-
})
214-
end
215-
build_response(response)
155+
batch_subscribe_instance_ids_to_topic([iid_token], topic_name)
216156
end
217157

218158
def unsubscribe_instance_id_from_topic iid_token, topic_name
219-
response = nil
220-
for_uri(INSTANCE_ID_API) do
221-
response = self.class.post('/v1/'+iid_token+'/rel/topics/'+topic_name, headers: {
222-
'Authorization' => "key=#{@api_key}",
223-
'Content-type' => 'application/json'
224-
})
225-
end
226-
build_response(response)
159+
batch_unsubscribe_instance_ids_from_topic([iid_token], topic_name)
227160
end
228161

229162
def batch_subscribe_instance_ids_to_topic instance_ids, topic_name
230-
response = nil
231-
for_uri(INSTANCE_ID_API) do
232-
response = self.class.post('/v1:batchAdd', body:{
233-
to: "/topics/#{topic_name}",
234-
registration_tokens: instance_ids
235-
}.to_json,
236-
headers: {
237-
'Authorization' => "key=#{@api_key}",
238-
'Content-type' => 'application/json'
239-
}
240-
)
241-
end
242-
build_response(response)
163+
manage_topics_relationship(topic_name, instance_ids, 'Add')
243164
end
244165

245166
def batch_unsubscribe_instance_ids_from_topic instance_ids, topic_name
246-
response = nil
247-
for_uri(INSTANCE_ID_API) do
248-
response = self.class.post('/v1:batchRemove', body: {
249-
to: "/topics/#{topic_name}",
250-
registration_tokens: instance_ids
251-
}.to_json,
252-
headers: {
253-
'Authorization' => "key=#{@api_key}",
254-
'Content-type' => 'application/json'
255-
}
256-
)
257-
end
258-
build_response(response)
167+
manage_topics_relationship(topic_name, instance_ids, 'Remove')
259168
end
260169

261170
def send_to_topic_condition(condition, options = {})
@@ -267,11 +176,16 @@ def send_to_topic_condition(condition, options = {})
267176

268177
private
269178

270-
def for_uri(uri)
271-
current_uri = self.class.base_uri
272-
self.class.base_uri uri
273-
yield
274-
self.class.base_uri current_uri
179+
def for_uri(uri, extra_headers = {})
180+
connection = ::Faraday.new(:url => uri) do |faraday|
181+
faraday.adapter Faraday.default_adapter
182+
faraday.headers["Content-Type"] = "application/json"
183+
faraday.headers["Authorization"] = "key=#{api_key}"
184+
extra_headers.each do |key, value|
185+
faraday.headers[key] = value
186+
end
187+
end
188+
yield connection
275189
end
276190

277191
def build_post_body(registration_ids, options = {})
@@ -281,8 +195,8 @@ def build_post_body(registration_ids, options = {})
281195

282196
def build_response(response, registration_ids = [])
283197
body = response.body || {}
284-
response_hash = { body: body, headers: response.headers, status_code: response.code }
285-
case response.code
198+
response_hash = { body: body, headers: response.headers, status_code: response.status }
199+
case response.status
286200
when 200
287201
response_hash[:response] = 'success'
288202
body = JSON.parse(body) unless body.empty?
@@ -325,16 +239,10 @@ def build_not_registered_ids(body, registration_id)
325239
end
326240

327241
def execute_notification(body)
328-
params = {
329-
body: body.to_json,
330-
headers: {
331-
'Authorization' => "key=#{@api_key}",
332-
'Content-Type' => 'application/json'
333-
}
334-
}
335-
336-
response = self.class.post('/send', params.merge(@client_options))
337-
build_response(response)
242+
for_uri(BASE_URI) do |connection|
243+
response = connection.post('/fcm/send', body.to_json)
244+
build_response(response)
245+
end
338246
end
339247

340248
def has_canonical_id?(result)

spec/fcm_spec.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
require 'spec_helper'
22

33
describe FCM do
4-
let(:send_url) { "#{FCM.base_uri}/send" }
5-
let(:group_notification_base_uri) { "https://android.googleapis.com/gcm/notification" }
4+
let(:send_url) { "#{FCM::BASE_URI}/fcm/send" }
5+
let(:group_notification_base_uri) { "#{FCM::GROUP_NOTIFICATION_BASE_URI}/gcm/notification" }
66
let(:api_key) { 'AIzaSyB-1uEai2WiUapxCs2Q0GZYzPu7Udno5aA' }
77
let(:registration_id) { '42' }
88
let(:registration_ids) { ['42'] }
@@ -254,7 +254,7 @@
254254

255255
it 'should not send notification due to 599' do
256256
subject.send(registration_ids).should eq(body: '{"body-key" => "Body value"}',
257-
headers: { 'header-key' => ['Header value'] },
257+
headers: { 'header-key' => 'Header value' },
258258
response: 'There was an internal error in the FCM server while trying to process the request.',
259259
status_code: 599)
260260
end

0 commit comments

Comments
 (0)