Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ToothlessGear/node-gcm
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 4229b39b76349ed6718c3091d1003e064a746954
Choose a base ref
...
head repository: ToothlessGear/node-gcm
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: c6b9eab3b2183352ee00a66a5fd22b6887ce51b7
Choose a head ref

Commits on May 15, 2018

  1. Copy the full SHA
    843d9ba View commit details
  2. 1.0.1

    eladnava committed May 15, 2018
    Copy the full SHA
    e2a1a27 View commit details

Commits on May 21, 2018

  1. Copy the full SHA
    0c948c8 View commit details

Commits on May 23, 2018

  1. Copy the full SHA
    e319179 View commit details

Commits on May 24, 2018

  1. Merge pull request #320 from jkowalleck/request-2.87.0

    versionbumped dependency 'request'
    eladnava authored May 24, 2018
    Copy the full SHA
    debc2b2 View commit details

Commits on May 30, 2018

  1. Example on how to get tokens you should remove

    Include example of how to find the tokens which you couldn't send to.
    
    I'm maching the two arrays together and then filtering it to get a list of tokens.
    johanforssell authored May 30, 2018
    Copy the full SHA
    a1f0fe2 View commit details

Commits on May 31, 2018

  1. Updated for clarity

    johanforssell authored May 31, 2018
    Copy the full SHA
    a76584c View commit details

Commits on Jun 1, 2018

  1. Copy the full SHA
    f84f469 View commit details
  2. Update package.json

    johanforssell authored Jun 1, 2018
    Copy the full SHA
    4b3d9be View commit details
  3. Merge pull request #323 from johanforssell/patch-1

    README: Example on getting the tokens you should remove
    hypesystem authored Jun 1, 2018
    Copy the full SHA
    a63a4b4 View commit details

Commits on Oct 20, 2018

  1. adds mutableContent doku entry

    Thomas Vogel committed Oct 20, 2018
    Copy the full SHA
    aa79f76 View commit details

Commits on Oct 22, 2018

  1. removes duplicate line

    Thomas Vogel committed Oct 22, 2018
    Copy the full SHA
    2fd89a1 View commit details

Commits on Oct 23, 2018

  1. Merge pull request #328 from tomsvogel/master

    adds mutableContent doku entry
    eladnava authored Oct 23, 2018
    Copy the full SHA
    4b74526 View commit details

Commits on Jun 2, 2019

  1. Update example to find "bad" tokens

    Failed tokens can be found with a single `filter` operation over the `registrationTokens` using the 1:1 mapping with response data. Earlier example used `map` + `filter` to achieve the same result.
    sidhantpanda authored Jun 2, 2019
    Copy the full SHA
    1816786 View commit details

Commits on Jul 18, 2019

  1. Merge pull request #333 from sidhantpanda/patch-1

    Update example to find  "bad" tokens
    hypesystem authored Jul 18, 2019
    Copy the full SHA
    8bae681 View commit details

Commits on Nov 12, 2019

  1. Update broken links in README

    Closes #334.
    eladnava authored Nov 12, 2019
    Copy the full SHA
    8256971 View commit details
  2. Copy the full SHA
    05ebebd View commit details

Commits on Jan 14, 2020

  1. Copy the full SHA
    adfd4b0 View commit details
  2. added similar test cases.

    yog27ray committed Jan 14, 2020
    Copy the full SHA
    4eeb2cc View commit details

Commits on May 26, 2020

  1. Copy the full SHA
    33683d9 View commit details

Commits on May 28, 2020

  1. Update README with usage

    SpellChucker committed May 28, 2020
    Copy the full SHA
    859625a View commit details
  2. Fix syntax of link

    SpellChucker committed May 28, 2020
    Copy the full SHA
    e435347 View commit details
  3. Merge pull request #342 from SpellChucker/add-fcm-options-message

    Add fcm_options as allowed params to message object
    eladnava authored May 28, 2020
    Copy the full SHA
    db66259 View commit details
  4. Copy the full SHA
    456b0de View commit details

Commits on Jul 6, 2020

  1. Copy the full SHA
    2390554 View commit details
  2. Add unit tests for uri override

    Alexey.Pertu committed Jul 6, 2020
    Copy the full SHA
    6c77b95 View commit details
  3. Move options.uri to overridable section

    Normally there is no need to override send URI
    except for testing
    Alexey.Pertu committed Jul 6, 2020
    Copy the full SHA
    fcb8d8c View commit details

Commits on Jul 9, 2020

  1. Merge pull request #345 from pertu/allow-uri-override

    Allow uri override
    eladnava authored Jul 9, 2020
    Copy the full SHA
    6d0bcc6 View commit details
  2. 1.0.2

    eladnava committed Jul 9, 2020
    Copy the full SHA
    cbb1115 View commit details
  3. 1.0.3

    eladnava committed Jul 9, 2020
    Copy the full SHA
    4bec224 View commit details

Commits on Jan 20, 2021

  1. use request@2.88.0

    marneborn committed Jan 20, 2021
    Copy the full SHA
    2b82cac View commit details
  2. upgrade lodash

    marneborn committed Jan 20, 2021
    Copy the full SHA
    29bb027 View commit details

Commits on Feb 23, 2021

  1. Merge pull request #337 from yog27ray/internalServer

    fix: Gcm InternalServerError should also be retied with exponential-back-off.
    ToothlessGear authored Feb 23, 2021
    Copy the full SHA
    dc80fc5 View commit details
  2. Merge pull request #349 from marneborn/upgrade-request

    dependency upgrades for vulnerabilities flagged by snyk
    ToothlessGear authored Feb 23, 2021
    Copy the full SHA
    72a883f View commit details
  3. 1.0.4

    ToothlessGear committed Feb 23, 2021
    Copy the full SHA
    31e89bd View commit details

Commits on Aug 28, 2021

  1. Copy the full SHA
    f268b8b View commit details
  2. 1.0.5

    eladnava committed Aug 28, 2021
    Copy the full SHA
    345392c View commit details

Commits on Oct 15, 2021

  1. Copy the full SHA
    a4df9a3 View commit details

Commits on Mar 11, 2022

  1. Copy the full SHA
    924a4f8 View commit details

Commits on Jul 30, 2022

  1. ci: add CI tests (#361)

    mtrezza authored Jul 30, 2022
    Copy the full SHA
    46f03d7 View commit details
  2. Copy the full SHA
    e034e7d View commit details

Commits on Sep 8, 2022

  1. Copy the full SHA
    d5cfe6a View commit details

Commits on Sep 21, 2023

  1. Replace request with axios (#372) (thanks @pmb-cl)

    * replace request with axios
    
    * bumping pkg version
    
    * changes for axios
    
    * fixed tests
    
    * small update to comment
    
    * putting test back
    
    * using a tilda for axios version
    
    * compiled in nodev12
    pmb-cl authored Sep 21, 2023
    Copy the full SHA
    42afc1b View commit details
  2. Copy the full SHA
    c6b9eab View commit details
Showing with 989 additions and 494 deletions.
  1. +50 −0 .github/workflows/ci.yml
  2. +22 −12 README.md
  3. +2 −1 lib/constants.js
  4. +7 −4 lib/message-options.js
  5. +35 −27 lib/sender.js
  6. +758 −418 package-lock.json
  7. +9 −7 package.json
  8. +106 −25 test/unit/senderSpec.js
50 changes: 50 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: ci
on:
push:
branches: [ master ]
pull_request:
branches:
- '**'
jobs:
check-lock-file-version:
name: NPM Lock File Version
timeout-minutes: 5
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Check NPM lock file version
uses: mansona/npm-lockfile-version@v1
with:
version: 1
build:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- name: Node 12
NODE_VERSION: 12
- name: Node 14
NODE_VERSION: 14
- name: Node 16
NODE_VERSION: 16
- name: Node 18
NODE_VERSION: 18
timeout-minutes: 30
env:
NODE_VERSION: ${{ matrix.NODE_VERSION }}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.NODE_VERSION }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.NODE_VERSION }}
- name: Cache Node.js modules
uses: actions/cache@v2
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
- run: npm ci
- run: npm run test
34 changes: 22 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -28,11 +28,11 @@ $ npm install node-gcm --save

## Requirements

This library provides the server-side implementation of GCM.
You need to generate an [API Key](https://developers.google.com/cloud-messaging/gcm#apikey).
This library provides the server-side implementation of FCM.
You need to generate a [Legacy API Server Key](https://console.firebase.google.com/u/0/) (Click the gear next to FCM project name) > Project Settings > Cloud Messaging -> **Cloud Messaging API (Legacy)** -> Click the 3 dots -> Manage API in Google Cloud Console -> **Enable** -> Go back and refresh Firebase Cloud Messaging project settings page to view your **Server key**.

GCM notifications can be sent to both [Android](https://developers.google.com/cloud-messaging/android/start) and [iOS](https://developers.google.com/cloud-messaging/ios/start).
If you are new to GCM you should probably look into the [documentation](https://developers.google.com/cloud-messaging/gcm).
FCM notifications can be sent to both [Android](https://firebase.google.com/docs/cloud-messaging/android/client) and [iOS](https://firebase.google.com/docs/cloud-messaging/ios/client).
If you are new to FCM you should probably look into the [documentation](https://firebase.google.com/docs/cloud-messaging).

## Example application

@@ -125,6 +125,14 @@ sender.send(message, { registrationTokens: registrationTokens }, 10, function (e
if(err) console.error(err);
else console.log(response);
});

// Q: I need to remove all expired / unregistered tokens from my database, how do I do that?
// The results-array does not contain any tokens!
// A: The array of tokens used for sending will match the array of results, so you can cross-check them.
sender.send(message, { registrationTokens: registrationTokens }, function (err, response) {
var failed_tokens = registrationTokens.filter((token, i) => response.results[i].error === 'NotRegistered');
console.log('These tokens are no longer registered:', failed_tokens);
});
```
## Recipients

@@ -133,7 +141,7 @@ You can send push notifications to various recipient types by providing one of t

|Key|Type|Description|
|---|---|---|
|to|String|A single [registration token](https://developers.google.com/cloud-messaging/android/client#sample-register), [notification key](https://developers.google.com/cloud-messaging/notifications), or [topic](https://developers.google.com/cloud-messaging/topic-messaging).
|to|String|A single [registration token](https://firebase.google.com/docs/cloud-messaging/android/client#sample-register), [notification key](https://firebase.google.com/docs/cloud-messaging/android/device-group), or [topic](https://firebase.google.com/docs/cloud-messaging/android/topic-messaging).
|topic|String|A single publish/subscribe topic.
|condition|String|Multiple topics using the [condition](https://firebase.google.com/docs/cloud-messaging/topic-messaging) parameter.
|notificationKey|String|Deprecated. A key that groups multiple registration tokens linked to the same user.
@@ -143,7 +151,7 @@ You can send push notifications to various recipient types by providing one of t
If you provide an incorrect recipient key or object type, an `Error` object will be returned to your callback.

Notice that [you can *at most* send notifications to 1000 registration tokens at a time](https://github.com/ToothlessGear/node-gcm/issues/42).
This is due to [a restriction](http://developer.android.com/training/cloudsync/gcm.html) on the side of the GCM API.
This is due to [a restriction](https://firebase.google.com/docs/cloud-messaging/http-server-ref#downstream-http-messages-json) on the side of the FCM API.


### Additional message options
@@ -153,11 +161,13 @@ This is due to [a restriction](http://developer.android.com/training/cloudsync/g
|collapseKey|Optional, string|This parameter identifies a group of messages that can be collapsed, so that only the last message gets sent when delivery can be resumed.|
|priority|Optional, string|Sets the priority of the message. Valid values are "normal" and "high."|
|contentAvailable|Optional, JSON boolean|On iOS, when a notification or message is sent and this is set to true, an inactive client app is awoken.|
|timeToLive|Optional, JSON number|This parameter specifies how long (in seconds) the message should be kept in GCM storage if the device is offline. The maximum time to live supported is 4 weeks, and the default value is 4 weeks.|
|mutableContent|Optional, JSON boolean|On iOS, Currently for iOS 10+ devices only. On iOS, use this field to represent mutable-content in the APNs payload. When a notification is sent and this is set to true, the content of the notification can be modified before it is displayed, using a Notification Service app extension.|
|timeToLive|Optional, JSON number|This parameter specifies how long (in seconds) the message should be kept in FCM storage if the device is offline. The maximum time to live supported is 4 weeks, and the default value is 4 weeks.|
|restrictedPackageName|Optional, string|This parameter specifies the package name of the application where the registration tokens must match in order to receive the message.|
|dryRun|Optional, JSON boolean|This parameter, when set to true, allows developers to test a request without actually sending a message.|
|data|Optional, JSON object|This parameter specifies the custom key-value pairs of the message's payload.|
|notification|Optional, JSON object|This parameter specifies the predefined, user-visible key-value pairs of the notification payload. See "Notification payload option table" below for more details.|
|fcm_options|Optional, JSON object|This parameter is used to pass FCM specific options, as outlined [here](https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages#FcmOptions).

## Notification usage

@@ -198,11 +208,11 @@ message.addNotification({
|title_loc_args|iOS|Optional, JSON array as string|Indicates the string value to replace format specifiers in title string for localization. On iOS, this corresponds to "title-loc-args" in APNS payload.|
|title_loc_key|iOS|Optional, string|Indicates the key to the title string for localization. On iOS, this corresponds to "title-loc-key" in APNS payload.|

Notice notification payload defined in [GCM Connection Server Reference](https://developers.google.com/cloud-messaging/server-ref#table1)
Notice notification payload defined in [FCM Connection Server Reference](https://firebase.google.com/docs/cloud-messaging/http-server-ref#downstream-http-messages-json)

## Custom HTTP request options

You can provide custom `request` options such as `proxy` and `timeout` for the HTTP request to the GCM API. For more information, refer to [the complete list of request options](https://github.com/request/request#requestoptions-callback). Note that the following options cannot be overriden: `method`, `uri`, `body`, as well as the following headers: `Authorization`, `Content-Type`, and `Content-Length`.
You can provide custom `request` options such as `proxy` and `timeout` for the HTTP request to the FCM API. For more information, refer to [the complete list of request options](https://github.com/request/request#requestoptions-callback). Note that the following options cannot be overriden: `method`, `uri`, `body`, as well as the following headers: `Authorization`, `Content-Type`, and `Content-Length`.

```js
// Set custom request options
@@ -223,9 +233,9 @@ sender.send(message, { registrationTokens: regTokens }, function (err, response)
});
```

## GCM client compatibility
## FCM client compatibility

As of January 9th, 2016, there are a few known compatibility issues with 3rd-party GCM client libraries:
As of January 9th, 2016, there are a few known compatibility issues with 3rd-party FCM client libraries:

### phonegap-plugin-push

@@ -237,7 +247,7 @@ These issues are out of this project's context and can only be fixed by the resp

## Debug

To enable debug mode (print requests and responses to and from GCM),
To enable debug mode (print requests and responses to and from FCM),
set the `DEBUG` environment flag when running your app (assuming you use `node app.js` to run your app):

```bash
3 changes: 2 additions & 1 deletion lib/constants.js
Original file line number Diff line number Diff line change
@@ -33,7 +33,8 @@ var Constants = {
'ERROR_NOT_REGISTERED' : 'NotRegistered',
'ERROR_MESSAGE_TOO_BIG' : 'MessageTooBig',
'ERROR_MISSING_COLLAPSE_KEY' : 'MissingCollapseKey',
'ERROR_UNAVAILABLE' : 'Unavailable'
'ERROR_UNAVAILABLE' : 'Unavailable',
'ERROR_INTERNAL_SERVER_ERROR' : 'InternalServerError'

/** END DEPRECATED **/
};
11 changes: 7 additions & 4 deletions lib/message-options.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
/**
* This module defines all the arguments that may be passed to a message.
*
*
* Each argument may contain a field `__argName`, if the name of the field
* should be different when sent to the server.
*
*
* The argument may also contain a field `__argType`, if the given
* argument must be of that type. The types are the strings resulting from
* calling `typeof <arg>` where `<arg>` is the argument.
*
*
* Other than that, the arguments are expected to follow the indicated
* structure.
*/

module.exports = {
collapseKey: {
collapseKey: {
__argName: "collapse_key",
__argType: "string"
},
@@ -51,5 +51,8 @@ module.exports = {
__argType: "object"
//TODO: There are a lot of very specific arguments that could
// be indicated here.
},
fcm_options: {
__argType: "object"
}
};
62 changes: 35 additions & 27 deletions lib/sender.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
var Constants = require('./constants');
var _ = require('lodash');
var request = require('request');
var request = require('axios');
var debug = require('debug')('node-gcm');

function Sender(key, options) {
@@ -106,7 +106,7 @@ function checkForBadTokens(results, originalRecipients, callback) {
var unsentRegTokens = [];
var regTokenPositionMap = [];
for (var i = 0; i < results.length; i++) {
if (results[i].error === 'Unavailable') {
if (results[i].error === 'Unavailable' || results[i].error === 'InternalServerError') {
regTokenPositionMap.push(i);
unsentRegTokens.push(originalRecipients[i]);
}
@@ -147,36 +147,44 @@ Sender.prototype.sendNoRetry = function(message, recipient, callback) {
method: 'POST',
headers: {
'Authorization': 'key=' + this.key
},
uri: Constants.GCM_SEND_URI,
json: body
}
}, this.options, {
timeout: Constants.SOCKET_TIMEOUT
});

request(request_options, function (err, res, resBodyJSON) {
if (err) {
// overloading the post function to make testing it easier
request.post(request_options.uri || Constants.GCM_SEND_URI, body, request_options, callback)
.then((res) => {
const { data: resBodyJSON, status } = res;

if (status !== 200) {
debug('Invalid request (' + status + '): ' + resBodyJSON);
return callback(status);
}

if (_.isEmpty(resBodyJSON)) {
debug('Empty response received (' + status + ' ' + res.statusText + ')');
// Spoof error code 400 to avoid retrying the request
return callback({error: res.statusText, code: 400});
}

callback(null, resBodyJSON, body.registration_ids || [ body.to ]);
},
(err) => {
const { response: res } = err;

if (res.status === 401) {
debug('Unauthorized (401). Check that your API token is correct.');
return callback(res.status);
}

if (res.status >= 500) {
debug('GCM service is unavailable (500)');
return callback(res.status);
}

return callback(err);
}
if (res.statusCode >= 500) {
debug('GCM service is unavailable (500)');
return callback(res.statusCode);
}
if (res.statusCode === 401) {
debug('Unauthorized (401). Check that your API token is correct.');
return callback(res.statusCode);
}
if (res.statusCode !== 200) {
debug('Invalid request (' + res.statusCode + '): ' + resBodyJSON);
return callback(res.statusCode);
}
if (!resBodyJSON) {
debug('Empty response received (' + res.statusCode + ' ' + res.statusMessage + ')');
// Spoof error code 400 to avoid retrying the request
return callback({error: res.statusMessage, code: 400});
}
callback(null, resBodyJSON, body.registration_ids || [ body.to ]);
});
});
}.bind(this));
};

Loading