Skip to content
This repository has been archived by the owner on Apr 23, 2021. It is now read-only.

Allow sending with no payload, plus some small fixes #17

Merged
merged 3 commits into from
Apr 28, 2016
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/encrypt.js
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,4 @@ function encryptPayload(plaintext, contentEncryptionKey, nonce) {
return Buffer.concat([result, cipher.getAuthTag()]);
}

// All functions are exported here to make them testable, but only `encrypt` is
// re-exported by `index.js` as part of the public API.
module.exports = encrypt;
3 changes: 2 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ const push = require('./push');
*/
module.exports = {
encrypt: encrypt,
sendWebPush: push
sendWebPush: push.sendWebPush,
setGCMAPIKey: push.setGCMAPIKey
};
47 changes: 32 additions & 15 deletions src/push.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ const encrypt = require('./encrypt');
const GCM_URL = 'https://android.googleapis.com/gcm/send';
const TEMP_GCM_URL = 'https://gcm-http.googleapis.com/gcm';

let gcmAuthToken;

/**
* Set the key to use in the Authentication header for GCM requests
* @param {String} key The API key to use
*/
function setGCMAPIKey(key) {
gcmAuthToken = key;
}

/**
* URL safe Base64 encoder
*
Expand All @@ -42,13 +52,12 @@ function ub64(buffer) {
* @param {String} message The message to send
* @param {Object} subscription The subscription details for the client we
* are sending to
* @param {String} authToken Optional token to be used in the
* `Authentication` header if the endpoint
* requires it.
* @param {Number} paddingLength The number of bytes of padding to add to the
* message before encrypting it.
* @return {Promise} A promise that resolves if the push was sent successfully
* with status and body.
*/
function sendWebPush(message, subscription, authToken) {
function sendWebPush(message, subscription, paddingLength) {
if (!subscription || !subscription.endpoint) {
throw new Error('sendWebPush() expects a subscription endpoint with ' +
'an endpoint parameter.');
Expand All @@ -58,23 +67,31 @@ function sendWebPush(message, subscription, authToken) {
// GCM servers support the Web Push protocol. This should go away in the
// future.
const endpoint = subscription.endpoint.replace(GCM_URL, TEMP_GCM_URL);

const payload = encrypt(message, subscription);
const headers = {
'Content-Encoding': 'aesgcm',
'Encryption': `salt=${ub64(payload.salt)}`,
'Crypto-Key': `dh=${ub64(payload.serverPublicKey)}`
// TODO: Make TTL variable
Ttl: '0'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mega nit, shouldn't this be TTL similar to: https://github.com/gauntface/simple-push-demo/pull/28/files

};
let body;

if (message && message.length > 0) {
const payload = encrypt(message, subscription, paddingLength);
headers['Content-Encoding'] = 'aesgcm';
headers.Encryption = `salt=${ub64(payload.salt)}`;
headers['Crypto-Key'] = `dh=${ub64(payload.serverPublicKey)}`;
body = payload.ciphertext;
}

if (authToken) {
headers.Authorization = `key=${authToken}`;
} else if (endpoint.indexOf(TEMP_GCM_URL) !== -1) {
throw new Error('GCM requires an Auth Token parameter');
if (endpoint.indexOf(TEMP_GCM_URL) !== -1) {
if (gcmAuthToken) {
headers.Authorization = `key=${gcmAuthToken}`;
} else {
throw new Error('GCM requires an Auth Token parameter');
}
}

return new Promise(function(resolve, reject) {
request.post(endpoint, {
body: payload.ciphertext,
body: body,
headers: headers
}, function(error, response, body) {
if (error) {
Expand All @@ -101,4 +118,4 @@ function sendWebPush(message, subscription, authToken) {
});
}

module.exports = sendWebPush;
module.exports = {sendWebPush, setGCMAPIKey};
5 changes: 3 additions & 2 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ describe('Test the Libraries Top Level API', function() {
const library = proxyquire('../src/index.js', {
'./push': pushProxy
});
return library.sendWebPush('Hello, World!', VALID_SUBSCRIPTION)
return library.sendWebPush(new Buffer('Hello, World!', 'utf8'), VALID_SUBSCRIPTION)
.then(response => {
response.statusCode.should.equal(200);
response.statusMessage.should.equal('Status message');
Expand Down Expand Up @@ -338,7 +338,8 @@ describe('Test the Libraries Top Level API', function() {
const library = proxyquire('../src/index.js', {
'./push': pushProxy
});
return library.sendWebPush('Hello, World!', gcmSubscription, API_KEY)
library.setGCMAPIKey(API_KEY);
return library.sendWebPush('Hello, World!', gcmSubscription)
.then(response => {
response.statusCode.should.equal(200);
response.statusMessage.should.equal('Status message');
Expand Down