@@ -66,38 +66,39 @@ WebPushLib.prototype.setVapidDetails =
6666 } ;
6767 } ;
6868
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 =
8485 function ( subscription , payload , options ) {
8586 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 ' +
8788 'an endpoint.' ) ;
8889 }
8990
9091 if ( typeof subscription . endpoint !== 'string' ||
9192 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 ' +
9394 'a valid URL.' ) ;
9495 }
9596
9697 if ( payload ) {
9798 // Validate the subscription keys
9899 if ( ! subscription . keys || ! subscription . keys . p256dh ||
99100 ! 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 ' +
101102 'subscription must have \'auth\' and \'p256dh\' keys.' ) ;
102103 }
103104 }
@@ -116,7 +117,7 @@ WebPushLib.prototype.sendNotification =
116117 for ( let i = 0 ; i < optionKeys . length ; i += 1 ) {
117118 const optionKey = optionKeys [ i ] ;
118119 if ( validOptionKeys . indexOf ( optionKey ) === - 1 ) {
119- return Promise . reject ( '\'' + optionKey + '\' is an invalid option. ' +
120+ throw new Error ( '\'' + optionKey + '\' is an invalid option. ' +
120121 'The valid options are [\'' + validOptionKeys . join ( '\', \'' ) +
121122 '\'].' ) ;
122123 }
@@ -139,7 +140,7 @@ WebPushLib.prototype.sendNotification =
139140 timeToLive = DEFAULT_TTL ;
140141 }
141142
142- const requestOptions = {
143+ const requestDetails = {
143144 method : 'POST' ,
144145 headers : {
145146 TTL : timeToLive
@@ -152,27 +153,23 @@ WebPushLib.prototype.sendNotification =
152153 typeof subscription !== 'object' ||
153154 ! subscription . keys . p256dh ||
154155 ! 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 ' +
156157 'payload to this subscription since it doesn\'t have the ' +
157158 'required encryption keys' ) ) ;
158159 }
159160
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 ) ;
163163
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 ) ;
169169
170- requestPayload = encrypted . cipherText ;
171- } catch ( err ) {
172- return Promise . reject ( err ) ;
173- }
170+ requestPayload = encrypted . cipherText ;
174171 } else {
175- requestOptions . headers [ 'Content-Length' ] = 0 ;
172+ requestDetails . headers [ 'Content-Length' ] = 0 ;
176173 }
177174
178175 const isGCM = subscription . endpoint . indexOf (
@@ -183,7 +180,7 @@ WebPushLib.prototype.sendNotification =
183180 console . warn ( 'Attempt to send push notification to GCM endpoint, ' +
184181 'but no GCM key is defined' . bold . red ) ;
185182 } else {
186- requestOptions . headers . Authorization = 'key=' + currentGCMAPIKey ;
183+ requestDetails . headers . Authorization = 'key=' + currentGCMAPIKey ;
187184 }
188185 } else if ( currentVapidDetails ) {
189186 const parsedUrl = url . parse ( subscription . endpoint ) ;
@@ -197,22 +194,56 @@ WebPushLib.prototype.sendNotification =
197194 currentVapidDetails . privateKey
198195 ) ;
199196
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' ] += ';' +
203200 vapidHeaders [ 'Crypto-Key' ] ;
204201 } else {
205- requestOptions . headers [ 'Crypto-Key' ] = vapidHeaders [ 'Crypto-Key' ] ;
202+ requestDetails . headers [ 'Crypto-Key' ] = vapidHeaders [ 'Crypto-Key' ] ;
206203 }
207204 }
208205
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+
209236 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 ;
214245
215- const pushRequest = https . request ( requestOptions , function ( pushResponse ) {
246+ const pushRequest = https . request ( httpsOptions , function ( pushResponse ) {
216247 let responseText = '' ;
217248
218249 pushResponse . on ( 'data' , function ( chunk ) {
@@ -237,8 +268,8 @@ WebPushLib.prototype.sendNotification =
237268 reject ( e ) ;
238269 } ) ;
239270
240- if ( requestPayload ) {
241- pushRequest . write ( requestPayload ) ;
271+ if ( requestDetails . body ) {
272+ pushRequest . write ( requestDetails . body ) ;
242273 }
243274
244275 pushRequest . end ( ) ;
0 commit comments