@@ -66,38 +66,39 @@ WebPushLib.prototype.setVapidDetails =
66
66
} ;
67
67
} ;
68
68
69
- /**
70
- * To send a push notification call this method with a subscription, optional
71
- * payload and any options.
72
- * @param {PushSubscription } subscription The PushSubscription you wish to
73
- * send the notification to.
74
- * @param {string } [payload] The payload you wish to send to the
75
- * the user.
76
- * @param {Object } [options] Options for the GCM API key and
77
- * vapid keys can be passed in if they are unique for each notification you
78
- * wish to send.
79
- * @return {Promise } This method returns a Promise which
80
- * resolves if the sending of the notification was successful, otherwise it
81
- * rejects.
82
- */
83
- WebPushLib . prototype . sendNotification =
69
+ /**
70
+ * To get the details of a request to trigger a push message, without sending
71
+ * a push notification call this method.
72
+ *
73
+ * This method will throw an error if there is an issue with the input.
74
+ * @param {PushSubscription } subscription The PushSubscription you wish to
75
+ * send the notification to.
76
+ * @param {string } [payload] The payload you wish to send to the
77
+ * the user.
78
+ * @param {Object } [options] Options for the GCM API key and
79
+ * vapid keys can be passed in if they are unique for each notification you
80
+ * wish to send.
81
+ * @return {Object } This method returns an Object which
82
+ * contains 'endpoint', 'method', 'headers' and 'payload'.
83
+ */
84
+ WebPushLib . prototype . generateRequestDetails =
84
85
function ( subscription , payload , options ) {
85
86
if ( ! subscription || ! subscription . endpoint ) {
86
- return Promise . reject ( 'You must pass in a subscription with at least ' +
87
+ throw new Error ( 'You must pass in a subscription with at least ' +
87
88
'an endpoint.' ) ;
88
89
}
89
90
90
91
if ( typeof subscription . endpoint !== 'string' ||
91
92
subscription . endpoint . length === 0 ) {
92
- return Promise . reject ( 'The subscription endpoint must be a string with ' +
93
+ throw new Error ( 'The subscription endpoint must be a string with ' +
93
94
'a valid URL.' ) ;
94
95
}
95
96
96
97
if ( payload ) {
97
98
// Validate the subscription keys
98
99
if ( ! subscription . keys || ! subscription . keys . p256dh ||
99
100
! subscription . keys . auth ) {
100
- return Promise . reject ( 'To send a message with a payload, the ' +
101
+ throw new Error ( 'To send a message with a payload, the ' +
101
102
'subscription must have \'auth\' and \'p256dh\' keys.' ) ;
102
103
}
103
104
}
@@ -116,7 +117,7 @@ WebPushLib.prototype.sendNotification =
116
117
for ( let i = 0 ; i < optionKeys . length ; i += 1 ) {
117
118
const optionKey = optionKeys [ i ] ;
118
119
if ( validOptionKeys . indexOf ( optionKey ) === - 1 ) {
119
- return Promise . reject ( '\'' + optionKey + '\' is an invalid option. ' +
120
+ throw new Error ( '\'' + optionKey + '\' is an invalid option. ' +
120
121
'The valid options are [\'' + validOptionKeys . join ( '\', \'' ) +
121
122
'\'].' ) ;
122
123
}
@@ -139,7 +140,7 @@ WebPushLib.prototype.sendNotification =
139
140
timeToLive = DEFAULT_TTL ;
140
141
}
141
142
142
- const requestOptions = {
143
+ const requestDetails = {
143
144
method : 'POST' ,
144
145
headers : {
145
146
TTL : timeToLive
@@ -152,27 +153,23 @@ WebPushLib.prototype.sendNotification =
152
153
typeof subscription !== 'object' ||
153
154
! subscription . keys . p256dh ||
154
155
! subscription . keys . auth ) {
155
- return Promise . reject ( new Error ( 'Unable to send a message with ' +
156
+ throw new Error ( new Error ( 'Unable to send a message with ' +
156
157
'payload to this subscription since it doesn\'t have the ' +
157
158
'required encryption keys' ) ) ;
158
159
}
159
160
160
- try {
161
- const encrypted = encryptionHelper . encrypt (
162
- subscription . keys . p256dh , subscription . keys . auth , payload ) ;
161
+ const encrypted = encryptionHelper . encrypt (
162
+ subscription . keys . p256dh , subscription . keys . auth , payload ) ;
163
163
164
- requestOptions . headers [ 'Content-Length' ] = encrypted . cipherText . length ;
165
- requestOptions . headers [ 'Content-Type' ] = 'application/octet-stream' ;
166
- requestOptions . headers [ 'Content-Encoding' ] = 'aesgcm' ;
167
- requestOptions . headers . Encryption = 'salt=' + encrypted . salt ;
168
- requestOptions . headers [ 'Crypto-Key' ] = 'dh=' + urlBase64 . encode ( encrypted . localPublicKey ) ;
164
+ requestDetails . headers [ 'Content-Length' ] = encrypted . cipherText . length ;
165
+ requestDetails . headers [ 'Content-Type' ] = 'application/octet-stream' ;
166
+ requestDetails . headers [ 'Content-Encoding' ] = 'aesgcm' ;
167
+ requestDetails . headers . Encryption = 'salt=' + encrypted . salt ;
168
+ requestDetails . headers [ 'Crypto-Key' ] = 'dh=' + urlBase64 . encode ( encrypted . localPublicKey ) ;
169
169
170
- requestPayload = encrypted . cipherText ;
171
- } catch ( err ) {
172
- return Promise . reject ( err ) ;
173
- }
170
+ requestPayload = encrypted . cipherText ;
174
171
} else {
175
- requestOptions . headers [ 'Content-Length' ] = 0 ;
172
+ requestDetails . headers [ 'Content-Length' ] = 0 ;
176
173
}
177
174
178
175
const isGCM = subscription . endpoint . indexOf (
@@ -183,7 +180,7 @@ WebPushLib.prototype.sendNotification =
183
180
console . warn ( 'Attempt to send push notification to GCM endpoint, ' +
184
181
'but no GCM key is defined' . bold . red ) ;
185
182
} else {
186
- requestOptions . headers . Authorization = 'key=' + currentGCMAPIKey ;
183
+ requestDetails . headers . Authorization = 'key=' + currentGCMAPIKey ;
187
184
}
188
185
} else if ( currentVapidDetails ) {
189
186
const parsedUrl = url . parse ( subscription . endpoint ) ;
@@ -197,22 +194,56 @@ WebPushLib.prototype.sendNotification =
197
194
currentVapidDetails . privateKey
198
195
) ;
199
196
200
- requestOptions . headers . Authorization = vapidHeaders . Authorization ;
201
- if ( requestOptions . headers [ 'Crypto-Key' ] ) {
202
- requestOptions . headers [ 'Crypto-Key' ] += ';' +
197
+ requestDetails . headers . Authorization = vapidHeaders . Authorization ;
198
+ if ( requestDetails . headers [ 'Crypto-Key' ] ) {
199
+ requestDetails . headers [ 'Crypto-Key' ] += ';' +
203
200
vapidHeaders [ 'Crypto-Key' ] ;
204
201
} else {
205
- requestOptions . headers [ 'Crypto-Key' ] = vapidHeaders [ 'Crypto-Key' ] ;
202
+ requestDetails . headers [ 'Crypto-Key' ] = vapidHeaders [ 'Crypto-Key' ] ;
206
203
}
207
204
}
208
205
206
+ requestDetails . body = requestPayload ;
207
+ requestDetails . endpoint = subscription . endpoint ;
208
+
209
+ return requestDetails ;
210
+ } ;
211
+
212
+ /**
213
+ * To send a push notification call this method with a subscription, optional
214
+ * payload and any options.
215
+ * @param {PushSubscription } subscription The PushSubscription you wish to
216
+ * send the notification to.
217
+ * @param {string } [payload] The payload you wish to send to the
218
+ * the user.
219
+ * @param {Object } [options] Options for the GCM API key and
220
+ * vapid keys can be passed in if they are unique for each notification you
221
+ * wish to send.
222
+ * @return {Promise } This method returns a Promise which
223
+ * resolves if the sending of the notification was successful, otherwise it
224
+ * rejects.
225
+ */
226
+ WebPushLib . prototype . sendNotification =
227
+ function ( subscription , payload , options ) {
228
+ let requestDetails ;
229
+ try {
230
+ requestDetails = this . generateRequestDetails (
231
+ subscription , payload , options ) ;
232
+ } catch ( err ) {
233
+ return Promise . reject ( err ) ;
234
+ }
235
+
209
236
return new Promise ( function ( resolve , reject ) {
210
- const urlParts = url . parse ( subscription . endpoint ) ;
211
- requestOptions . hostname = urlParts . hostname ;
212
- requestOptions . port = urlParts . port ;
213
- requestOptions . path = urlParts . path ;
237
+ const httpsOptions = { } ;
238
+ const urlParts = url . parse ( requestDetails . endpoint ) ;
239
+ httpsOptions . hostname = urlParts . hostname ;
240
+ httpsOptions . port = urlParts . port ;
241
+ httpsOptions . path = urlParts . path ;
242
+
243
+ httpsOptions . headers = requestDetails . headers ;
244
+ httpsOptions . method = requestDetails . method ;
214
245
215
- const pushRequest = https . request ( requestOptions , function ( pushResponse ) {
246
+ const pushRequest = https . request ( httpsOptions , function ( pushResponse ) {
216
247
let responseText = '' ;
217
248
218
249
pushResponse . on ( 'data' , function ( chunk ) {
@@ -237,8 +268,8 @@ WebPushLib.prototype.sendNotification =
237
268
reject ( e ) ;
238
269
} ) ;
239
270
240
- if ( requestPayload ) {
241
- pushRequest . write ( requestPayload ) ;
271
+ if ( requestDetails . body ) {
272
+ pushRequest . write ( requestDetails . body ) ;
242
273
}
243
274
244
275
pushRequest . end ( ) ;
0 commit comments