Skip to content

Commit

Permalink
merging
Browse files Browse the repository at this point in the history
  • Loading branch information
Matt Gaunt committed Oct 14, 2016
1 parent 4efbc22 commit 6f02d24
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 46 deletions.
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ const webPush = new WebPushLib();

module.exports = {
encrypt: encryptionHelper.encrypt,
getVapidHeaders: vapidHelper.getVapidHeaders,
generateVAPIDKeys: vapidHelper.generateVAPIDKeys,
setGCMAPIKey: webPush.setGCMAPIKey,
setVapidDetails: webPush.setVapidDetails,
generateRequestDetails: webPush.generateRequestDetails,
sendNotification: webPush.sendNotification
};
126 changes: 80 additions & 46 deletions src/web-push-lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,38 +66,38 @@ WebPushLib.prototype.setVapidDetails =
};
};

/**
* To send a push notification call this method with a subscription, optional
* payload and any options.
* @param {PushSubscription} subscription The PushSubscription you wish to
* send the notification to.
* @param {string} [payload] The payload you wish to send to the
* the user.
* @param {Object} [options] Options for the GCM API key and
* vapid keys can be passed in if they are unique for each notification you
* wish to send.
* @return {Promise} This method returns a Promise which
* resolves if the sending of the notification was successful, otherwise it
* rejects.
*/
WebPushLib.prototype.sendNotification =
/**
* To send a push notification call this method with a subscription, optional
* payload and any options.
* @param {PushSubscription} subscription The PushSubscription you wish to
* send the notification to.
* @param {string} [payload] The payload you wish to send to the
* the user.
* @param {Object} [options] Options for the GCM API key and
* vapid keys can be passed in if they are unique for each notification you
* wish to send.
* @return {Promise} This method returns a Promise which
* resolves if the sending of the notification was successful, otherwise it
* rejects.
*/
WebPushLib.prototype.generateRequestDetails =
function(subscription, payload, options) {
if (!subscription || !subscription.endpoint) {
return Promise.reject('You must pass in a subscription with at least ' +
throw new Error('You must pass in a subscription with at least ' +
'an endpoint.');
}

if (typeof subscription.endpoint !== 'string' ||
subscription.endpoint.length === 0) {
return Promise.reject('The subscription endpoint must be a string with ' +
throw new Error('The subscription endpoint must be a string with ' +
'a valid URL.');
}

if (payload) {
// Validate the subscription keys
if (!subscription.keys || !subscription.keys.p256dh ||
!subscription.keys.auth) {
return Promise.reject('To send a message with a payload, the ' +
throw new Error('To send a message with a payload, the ' +
'subscription must have \'auth\' and \'p256dh\' keys.');
}
}
Expand All @@ -116,7 +116,7 @@ WebPushLib.prototype.sendNotification =
for (let i = 0; i < optionKeys.length; i += 1) {
const optionKey = optionKeys[i];
if (validOptionKeys.indexOf(optionKey) === -1) {
return Promise.reject('\'' + optionKey + '\' is an invalid option. ' +
throw new Error('\'' + optionKey + '\' is an invalid option. ' +
'The valid options are [\'' + validOptionKeys.join('\', \'') +
'\'].');
}
Expand All @@ -139,7 +139,7 @@ WebPushLib.prototype.sendNotification =
timeToLive = DEFAULT_TTL;
}

const requestOptions = {
const requestDetails = {
method: 'POST',
headers: {
TTL: timeToLive
Expand All @@ -152,27 +152,24 @@ WebPushLib.prototype.sendNotification =
typeof subscription !== 'object' ||
!subscription.keys.p256dh ||
!subscription.keys.auth) {
return Promise.reject(new Error('Unable to send a message with ' +
throw new Error(new Error('Unable to send a message with ' +
'payload to this subscription since it doesn\'t have the ' +
'required encryption keys'));
}

try {
const encrypted = encryptionHelper.encrypt(
subscription.keys.p256dh, subscription.keys.auth, payload);
try {
const encrypted = encryptionHelper.encrypt(
subscription.keys.p256dh, subscription.keys.auth, payload);

requestOptions.headers['Content-Length'] = encrypted.cipherText.length;
requestOptions.headers['Content-Type'] = 'application/octet-stream';
requestOptions.headers['Content-Encoding'] = 'aesgcm';
requestOptions.headers.Encryption = 'salt=' + encrypted.salt;
requestOptions.headers['Crypto-Key'] = 'dh=' + urlBase64.encode(encrypted.localPublicKey);
requestOptions.headers['Content-Length'] = encrypted.cipherText.length;
requestOptions.headers['Content-Type'] = 'application/octet-stream';
requestOptions.headers['Content-Encoding'] = 'aesgcm';
requestOptions.headers.Encryption = 'salt=' + encrypted.salt;
requestOptions.headers['Crypto-Key'] = 'dh=' + urlBase64.encode(encrypted.localPublicKey);

requestPayload = encrypted.cipherText;
} catch (err) {
return Promise.reject(err);
}
requestPayload = encrypted.cipherText;
} else {
requestOptions.headers['Content-Length'] = 0;
requestDetails.headers['Content-Length'] = 0;
}

const isGCM = subscription.endpoint.indexOf(
Expand All @@ -183,7 +180,7 @@ WebPushLib.prototype.sendNotification =
console.warn('Attempt to send push notification to GCM endpoint, ' +
'but no GCM key is defined'.bold.red);
} else {
requestOptions.headers.Authorization = 'key=' + currentGCMAPIKey;
requestDetails.headers.Authorization = 'key=' + currentGCMAPIKey;
}
} else if (currentVapidDetails) {
const parsedUrl = url.parse(subscription.endpoint);
Expand All @@ -197,22 +194,59 @@ WebPushLib.prototype.sendNotification =
currentVapidDetails.privateKey
);

requestOptions.headers.Authorization = vapidHeaders.Authorization;
if (requestOptions.headers['Crypto-Key']) {
requestOptions.headers['Crypto-Key'] += ';' +
requestDetails.headers.Authorization = vapidHeaders.Authorization;
if (requestDetails.headers['Crypto-Key']) {
requestDetails.headers['Crypto-Key'] += ';' +
vapidHeaders['Crypto-Key'];
} else {
requestOptions.headers['Crypto-Key'] = vapidHeaders['Crypto-Key'];
requestDetails.headers['Crypto-Key'] = vapidHeaders['Crypto-Key'];
}
}

requestDetails.payload = requestPayload;
requestDetails.endpoint = subscription.endpoint;

return requestDetails;
};

/**
* To send a push notification call this method with a subscription, optional
* payload and any options.
* @param {PushSubscription} subscription The PushSubscription you wish to
* send the notification to.
* @param {string} [payload] The payload you wish to send to the
* the user.
* @param {Object} [options] Options for the GCM API key and
* vapid keys can be passed in if they are unique for each notification you
* wish to send.
* @return {Promise} This method returns a Promise which
* resolves if the sending of the notification was successful, otherwise it
* rejects.
*/
WebPushLib.prototype.sendNotification =
function(subscription, payload, options) {
let requestDetails;
try {
requestDetails = this.generateRequestDetails(
subscription, payload, options);
} catch (err) {
return Promise.reject(err);
}

return new Promise(function(resolve, reject) {
const urlParts = url.parse(subscription.endpoint);
requestOptions.hostname = urlParts.hostname;
requestOptions.port = urlParts.port;
requestOptions.path = urlParts.path;
console.log(requestDetails);

const httpsOptions = {};
const urlParts = url.parse(requestDetails.endpoint);
httpsOptions.hostname = urlParts.hostname;
httpsOptions.port = urlParts.port;
httpsOptions.path = urlParts.path;

httpsOptions.headers = requestDetails.headers;

console.log(httpsOptions);

const pushRequest = https.request(requestOptions, function(pushResponse) {
const pushRequest = https.request(httpsOptions, function(pushResponse) {
let responseText = '';

pushResponse.on('data', function(chunk) {
Expand All @@ -237,8 +271,8 @@ WebPushLib.prototype.sendNotification =
reject(e);
});

if (requestPayload) {
pushRequest.write(requestPayload);
if (requestDetails.payload) {
pushRequest.write(requestDetails.payload);
}

pushRequest.end();
Expand Down

0 comments on commit 6f02d24

Please sign in to comment.