@@ -9,8 +9,15 @@ function Sender(key, options) {
99 return new Sender ( key , options ) ;
1010 }
1111
12- this . key = key ;
13- this . options = options || { } ;
12+ this . requestOptions = defaultsDeep ( {
13+ method : 'POST' ,
14+ headers : {
15+ 'Authorization' : 'key=' + key
16+ } ,
17+ uri : Constants . GCM_SEND_URI
18+ } , options , {
19+ timeout : Constants . SOCKET_TIMEOUT
20+ } ) ;
1421}
1522
1623Sender . prototype . send = function ( message , recipient , options , callback ) {
@@ -23,42 +30,15 @@ Sender.prototype.send = function(message, recipient, options, callback) {
2330 }
2431 options = cleanOptions ( options ) ;
2532
26- if ( options . retries == 0 ) {
27- return this . sendNoRetry ( message , recipient , callback ) ;
28- }
29-
30- var self = this ;
31-
32- this . sendNoRetry ( message , recipient , function ( err , response , attemptedRegTokens ) {
33- if ( err ) {
34- if ( typeof err === 'number' && err > 399 && err < 500 ) {
35- debug ( "Error 4xx -- no use retrying. Something is wrong with the request (probably authentication?)" ) ;
36- return callback ( err ) ;
37- }
38- return retry ( self , message , recipient , options , callback ) ;
33+ getRequestBody ( message , recipient , function ( err , body ) {
34+ if ( err ) {
35+ return callback ( err ) ;
3936 }
40- if ( ! response . results ) {
41- return callback ( null , response ) ;
37+ if ( options . retries == 0 ) {
38+ return sendMessage ( this . requestOptions , body , callback ) ;
4239 }
43- checkForBadTokens ( response . results , attemptedRegTokens , function ( err , unsentRegTokens , regTokenPositionMap ) {
44- if ( err ) {
45- return callback ( err ) ;
46- }
47- if ( unsentRegTokens . length == 0 ) {
48- return callback ( null , response ) ;
49- }
50-
51- debug ( "Retrying " + unsentRegTokens . length + " unsent registration tokens" ) ;
52-
53- retry ( self , message , unsentRegTokens , options , function ( err , retriedResponse ) {
54- if ( err ) {
55- return callback ( null , response ) ;
56- }
57- response = updateResponse ( response , retriedResponse , regTokenPositionMap , unsentRegTokens ) ;
58- callback ( null , response ) ;
59- } ) ;
60- } ) ;
61- } ) ;
40+ sendMessageWithRetries ( this . requestOptions , body , options , callback ) ;
41+ } . bind ( this ) ) ;
6242} ;
6343
6444function cleanOptions ( options ) {
@@ -86,13 +66,86 @@ function cleanOptions(options) {
8666 return options ;
8767}
8868
89- function retry ( self , message , recipient , options , callback ) {
90- return setTimeout ( function ( ) {
91- self . send ( message , recipient , {
92- retries : options . retries - 1 ,
93- backoff : options . backoff * 2
69+ function getRequestBody ( message , recipient , callback ) {
70+ var body = cleanParams ( message ) ;
71+
72+ if ( typeof recipient == "string" ) {
73+ body . to = recipient ;
74+ return nextTick ( callback , null , body ) ;
75+ }
76+ if ( Array . isArray ( recipient ) ) {
77+ if ( recipient . length < 1 ) {
78+ return nextTick ( callback , new Error ( 'Empty recipient array passed!' ) ) ;
79+ }
80+ body . registration_ids = recipient ;
81+ return nextTick ( callback , null , body ) ;
82+ }
83+ return nextTick ( callback , new Error ( 'Invalid recipient (' + recipient + ', type ' + typeof recipient + ') provided (must be array or string)!' ) ) ;
84+ }
85+
86+ function cleanParams ( raw ) {
87+ var params = { } ;
88+ Object . keys ( raw ) . forEach ( function ( param ) {
89+ var paramOptions = messageOptions [ param ] ;
90+ if ( ! paramOptions ) {
91+ return console . warn ( "node-gcm ignored unknown message parameter " + param ) ;
92+ }
93+ if ( paramOptions . __argType != typeof raw [ param ] ) {
94+ return console . warn ( "node-gcm ignored wrongly typed message parameter " + param + " (was " + typeof raw [ param ] + ", expected " + paramOptions . __argType + ")" ) ;
95+ }
96+ params [ param ] = raw [ param ] ;
97+ } ) ;
98+ return params ;
99+ }
100+
101+ function nextTick ( func ) {
102+ var args = Array . prototype . slice . call ( arguments , 1 ) ;
103+ process . nextTick ( function ( ) {
104+ func . apply ( this , args ) ;
105+ } . bind ( this ) ) ;
106+ }
107+
108+ function sendMessageWithRetries ( requestOptions , body , messageOptions , callback ) {
109+ sendMessage ( requestOptions , body , function ( err , response , attemptedRegTokens ) {
110+ if ( err ) {
111+ if ( typeof err === 'number' && err > 399 && err < 500 ) {
112+ debug ( "Error 4xx -- no use retrying. Something is wrong with the request (probably authentication?)" ) ;
113+ return callback ( err ) ;
114+ }
115+ return retry ( requestOptions , body , messageOptions , callback ) ;
116+ }
117+ checkForBadTokens ( response . results , attemptedRegTokens , function ( err , unsentRegTokens , regTokenPositionMap ) {
118+ if ( err ) {
119+ return callback ( err ) ;
120+ }
121+ if ( unsentRegTokens . length == 0 ) {
122+ return callback ( null , response ) ;
123+ }
124+
125+ debug ( "Retrying " + unsentRegTokens . length + " unsent registration tokens" ) ;
126+
127+ body . registration_ids = unsentRegTokens ;
128+ retry ( requestOptions , body , messageOptions , function ( err , retriedResponse ) {
129+ if ( err ) {
130+ return callback ( null , response ) ;
131+ }
132+ response = updateResponse ( response , retriedResponse , regTokenPositionMap , unsentRegTokens ) ;
133+ callback ( null , response ) ;
134+ } ) ;
135+ } ) ;
136+ } ) ;
137+ }
138+
139+ function retry ( requestOptions , body , messageOptions , callback ) {
140+ setTimeout ( function ( ) {
141+ if ( messageOptions . retries <= 1 ) {
142+ return sendMessage ( requestOptions , body , callback ) ;
143+ }
144+ sendMessageWithRetries ( requestOptions , body , {
145+ retries : messageOptions . retries - 1 ,
146+ backoff : messageOptions . backoff * 2
94147 } , callback ) ;
95- } , options . backoff ) ;
148+ } , messageOptions . backoff ) ;
96149}
97150
98151function checkForBadTokens ( results , originalRecipients , callback ) {
@@ -125,86 +178,26 @@ function updateResponseMetaData(response, retriedResponse, unsentRegTokens) {
125178 response . failure -= unsentRegTokens . length - retriedResponse . failure ;
126179}
127180
128- Sender . prototype . sendNoRetry = function ( message , recipient , callback ) {
129- if ( ! callback ) {
130- callback = function ( ) { } ;
131- }
132-
133- getRequestBody ( message , recipient , function ( err , body ) {
134- if ( err ) {
181+ function sendMessage ( requestOptions , body , callback ) {
182+ requestOptions . json = body ;
183+ request ( requestOptions , function ( err , res , resBodyJSON ) {
184+ if ( err ) {
135185 return callback ( err ) ;
136186 }
137-
138- //Build request options, allowing some to be overridden
139- var request_options = defaultsDeep ( {
140- method : 'POST' ,
141- headers : {
142- 'Authorization' : 'key=' + this . key
143- } ,
144- uri : Constants . GCM_SEND_URI ,
145- json : body
146- } , this . options , {
147- timeout : Constants . SOCKET_TIMEOUT
148- } ) ;
149-
150- request ( request_options , function ( err , res , resBodyJSON ) {
151- if ( err ) {
152- return callback ( err ) ;
153- }
154- if ( res . statusCode >= 500 ) {
155- debug ( 'GCM service is unavailable (500)' ) ;
156- return callback ( res . statusCode ) ;
157- }
158- if ( res . statusCode === 401 ) {
159- debug ( 'Unauthorized (401). Check that your API token is correct.' ) ;
160- return callback ( res . statusCode ) ;
161- }
162- if ( res . statusCode !== 200 ) {
163- debug ( 'Invalid request (' + res . statusCode + '): ' + resBodyJSON ) ;
164- return callback ( res . statusCode ) ;
165- }
166- callback ( null , resBodyJSON , body . registration_ids || [ body . to ] ) ;
167- } ) ;
168- } . bind ( this ) ) ;
169- } ;
170-
171- function getRequestBody ( message , recipient , callback ) {
172- var body = cleanParams ( message ) ;
173-
174- if ( typeof recipient == "string" ) {
175- body . to = recipient ;
176- return nextTick ( callback , null , body ) ;
177- }
178- if ( Array . isArray ( recipient ) ) {
179- if ( recipient . length < 1 ) {
180- return nextTick ( callback , new Error ( 'Empty recipient array passed!' ) ) ;
187+ if ( res . statusCode >= 500 ) {
188+ debug ( 'GCM service is unavailable (500)' ) ;
189+ return callback ( res . statusCode ) ;
181190 }
182- body . registration_ids = recipient ;
183- return nextTick ( callback , null , body ) ;
184- }
185- return nextTick ( callback , new Error ( 'Invalid recipient (' + recipient + ', type ' + typeof recipient + ') provided (must be array or string)!' ) ) ;
186- }
187-
188- function cleanParams ( raw ) {
189- var params = { } ;
190- Object . keys ( raw ) . forEach ( function ( param ) {
191- var paramOptions = messageOptions [ param ] ;
192- if ( ! paramOptions ) {
193- return console . warn ( "node-gcm ignored unknown message parameter " + param ) ;
191+ if ( res . statusCode === 401 ) {
192+ debug ( 'Unauthorized (401). Check that your API token is correct.' ) ;
193+ return callback ( res . statusCode ) ;
194194 }
195- if ( paramOptions . __argType != typeof raw [ param ] ) {
196- return console . warn ( "node-gcm ignored wrongly typed message parameter " + param + " (was " + typeof raw [ param ] + ", expected " + paramOptions . __argType + ")" ) ;
195+ if ( res . statusCode !== 200 ) {
196+ debug ( 'Invalid request (' + res . statusCode + '): ' + resBodyJSON ) ;
197+ return callback ( res . statusCode ) ;
197198 }
198- params [ param ] = raw [ param ] ;
199+ callback ( null , resBodyJSON , body . registration_ids || [ body . to ] ) ;
199200 } ) ;
200- return params ;
201- }
202-
203- function nextTick ( func ) {
204- var args = Array . prototype . slice . call ( arguments , 1 ) ;
205- process . nextTick ( function ( ) {
206- func . apply ( this , args ) ;
207- } . bind ( this ) ) ;
208201}
209202
210203module . exports = Sender ;
0 commit comments