Giter VIP home page Giter VIP logo

pusher-http-node's Introduction

Build Status npm version

Pusher Channels Node.js REST library

In order to use this library, you need to have an account on https://pusher.com/channels. After registering, you will need the application credentials for your app.

Supported platforms

This SDK supports Node.js version 10+.

We test the library against a selection of Node.js versions which we update over time. Please refer to test.yml for the set of versions that are currently tested with CI.

If you find any compatibility issues, please raise an issue in the repository or contact support at [email protected]. We will happily investigate reported problems ❤️.

Installation

You need to be running at least Node.js 10 to use this library.

$ npm install pusher

Importing

It's possible to use pusher-http-node with typescript or javascript.

const Pusher = require("pusher")
import * as Pusher from "pusher"

All external APIs should have types in index.d.ts.

Configuration

There are 3 ways to configure the client. First one is just using the Pusher constructor:

const Pusher = require("pusher")

const pusher = new Pusher({
  appId: "APP_ID",
  key: "APP_KEY",
  secret: "SECRET_KEY",
  useTLS: USE_TLS, // optional, defaults to false
  cluster: "CLUSTER", // if `host` is present, it will override the `cluster` option.
  host: "HOST", // optional, defaults to api.pusherapp.com
  port: PORT, // optional, defaults to 80 for non-TLS connections and 443 for TLS connections
  encryptionMasterKeyBase64: ENCRYPTION_MASTER_KEY, // a base64 string which encodes 32 bytes, used to derive the per-channel encryption keys (see below!)
})

For specific clusters, you can use the forCluster function. This is the same as using the cluster option in the constructor.

const Pusher = require("pusher")

const pusher = Pusher.forCluster("CLUSTER", {
  appId: "APP_ID",
  key: "APP_KEY",
  secret: "SECRET_KEY",
  useTLS: USE_TLS, // optional, defaults to false
  port: PORT, // optional, defaults to 80 for non-TLS connections and 443 for TLS connections
  encryptionMasterKeyBase64: ENCRYPTION_MASTER_KEY, // a base64 string which encodes 32 bytes, used to derive the per-channel encryption keys (see below!)
})

You can also specify auth and endpoint options by passing an URL:

const Pusher = require("pusher")

const pusher = Pusher.forURL(
  "SCHEME://APP_KEY:SECRET_KEY@HOST:PORT/apps/APP_ID"
)

You can pass the optional second argument with options, as in forCluster function.

This is useful for example on Heroku, which sets the PUSHER_URL environment variable to such URL, if you have the Pusher addon installed.

Additional options

There are a few additional options that can be used in all above methods:

const Pusher = require("pusher")

const pusher = new Pusher({
  // you can set other options in any of the 3 ways described above
  proxy: "HTTP_PROXY_URL", // optional, URL to proxy the requests through
  timeout: TIMEOUT, // optional, timeout for all requests in milliseconds
  keepAlive: KEEP_ALIVE, // optional, enables keep-alive, defaults to false
})

Usage

Callbacks and error handling

API requests

Asynchronous methods on the Pusher class (trigger, get and post) return a promise that resolves to a Response, or rejects with an error.

All operational errors are wrapped into a Pusher.RequestError object.

WebHooks

In case accessing data for invalid WebHooks, an Pusher.WebHookError exception will be thrown from the called method. It is recommended to validate the WebHook before interpreting it.

Publishing events

To send an event to one or more channels use the trigger function. Channel names can contain only characters which are alphanumeric, '_' or '-' and have to be at most 200 characters long. Event name can be at most 200 characters long too.

Single channel

pusher.trigger("channel-1", "test_event", { message: "hello world" })

Multiple channels

To trigger an event on multiple channels:

pusher.trigger(["channel-1", "channel-2"], "test_event", {
  message: "hello world",
})

You can trigger an event to at most 100 channels at once. Passing more than 100 channels will cause an exception to be thrown.

Batch events

If you wish to send multiple events in a single HTTP request, you can pass an array of events to pusher.triggerBatch. You can send up to a maximum of 10 events at once.

const events = [
  {
    channel: "channel-1",
    name: "test-event-1",
    data: { message: "hello world" },
  },
  {
    channel: "channel-2",
    name: "test-event-2",
    data: { message: "hello another world" },
  },
]

pusher.triggerBatch(events)

You can trigger a batch of up to 10 events.

Sending events to Authenticated Users

Events can be triggered to Authenticated Users

pusher.sendToUser("user-1", "test_event", { message: "hello world" })

Excluding event recipients

In order to avoid the client that triggered the event from also receiving it, a socket_id parameter can be added to the params object. For more information see: http://pusher.com/docs/publisher_api_guide/publisher_excluding_recipients.

pusher.trigger(channel, event, data, { socket_id: "1302.1081607" })

pusher.triggerBatch([
  { channel: channel, name: name, data: data, socket_id: "1302.1081607" },
])

Fetch subscriber and user counts at the time of publish [EXPERIMENTAL]

For the channels that were published to, you can request for the number of subscribers or user to be returned in the response body.

Regular triggering

pusher
  .trigger("presence-my-channel", "event", "test", { info: "user_count,subscription_count" })
  .then(response => {
    if (response.status !== 200) {
      throw Error("unexpected status")
    }
    // Parse the response body as JSON
    return response.json()
  )
  .then(body => {
    const channelsInfo = body.channels
    // Do something with channelsInfo
  })
  .catch(error => {
    // Handle error
  })

Batch triggering

const batch = [
  {
    channel: "my-channel",
    name: "event",
    data: "test1",
    info: "subscription_count",
  },
  {
    channel: "presence-my-channel",
    name: "event",
    data: "test2",
    info: "user_count,subscription_count",
  },
]
pusher
  .triggerBatch(batch)
  .then((response) => {
    if (response.status !== 200) {
      throw Error("unexpected status")
    }
    // Parse the response body as JSON
    return response.json()
  })
  .then((body) => {
    body.batch.forEach((attributes, i) => {
      process.stdout.write(
        `channel: ${batch[i].channel}, name: ${batch[i].name}, subscription_count: ${attributes.subscription_count}`
      )
      if ("user_count" in attributes) {
        process.stdout.write(`, user_count: ${attributes.user_count}`)
      }
      process.stdout.write("\n")
    })
  })
  .catch((error) => {
    console.error(error)
  })

End-to-end encryption

This library supports end-to-end encryption of your private channels. This means that only you and your connected clients will be able to read your messages. Pusher cannot decrypt them. You can enable this feature by following these steps:

  1. You should first set up Private channels. This involves creating an authorization endpoint on your server.

  2. Next, generate your 32 byte master encryption key, encode it as base64 and pass it to the Pusher constructor.

    This is secret and you should never share this with anyone. Not even Pusher.

    openssl rand -base64 32
    const pusher = new Pusher({
      appId: "APP_ID",
      key: "APP_KEY",
      secret: "SECRET_KEY",
      useTLS: true,
      encryptionMasterKeyBase64: "<KEY GENERATED BY PREVIOUS COMMAND>",
    })
  3. Channels where you wish to use end-to-end encryption should be prefixed with private-encrypted-.

  4. Subscribe to these channels in your client, and you're done! You can verify it is working by checking out the debug console on the https://dashboard.pusher.com/ and seeing the scrambled ciphertext.

Important note: This will not encrypt messages on channels that are not prefixed by private-encrypted-.

Limitation: you cannot trigger a single event on multiple channels in a call to trigger, e.g.

pusher.trigger(["channel-1", "private-encrypted-channel-2"], "test_event", {
  message: "hello world",
})

Rationale: the methods in this library map directly to individual Channels HTTP API requests. If we allowed triggering a single event on multiple channels (some encrypted, some unencrypted), then it would require two API requests: one where the event is encrypted to the encrypted channels, and one where the event is unencrypted for unencrypted channels.

Authenticating users

To authenticate users during sign in, you can use the authenticateUser function:

const userData = {
  id: "unique_user_id",
  name: "John Doe",
  image: "https://...",
}
const auth = pusher.authenticateUser(socketId, userData)

The userData parameter must contain an id property with a non empty string. For more information see: http://pusher.com/docs/authenticating_users

Terminating user connections

In order to terminate a user's connections, the user must have been authenticated. Check the Server user authentication docs for the information on how to create a user authentication endpoint.

To terminate all connections established by a given user, you can use the terminateUserConnections function:

pusher.terminateUserConnections(userId)

Please note, that it only terminates the user's active connections. This means, if nothing else is done, the user will be able to reconnect. For more information see: Terminating user connections docs.

Private channel authorisation

To authorise your users to access private channels on Pusher Channels, you can use the authorizeChannel function:

const auth = pusher.authorizeChannel(socketId, channel)

For more information see: http://pusher.com/docs/authenticating_users

Presence channel authorisation

Using presence channels is similar to private channels, but you can specify extra data to identify that particular user:

const channelData = {
  user_id: 'unique_user_id',
  user_info: {
    name: 'Phil Leggetter'
    twitter_id: '@leggetter'
  }
};
const auth = pusher.authorizeChannel(socketId, channel, channelData);

The auth is then returned to the caller as JSON.

For more information see: http://pusher.com/docs/authenticating_users

Application state

It's possible to query the state of the application using the pusher.get function.

pusher.get({ path: path, params: params })

The path property identifies the resource that the request should be made to and the params property should be a map of additional query string key and value pairs.

Params can't include following keys:

  • auth_key
  • auth_timestamp
  • auth_version
  • auth_signature
  • body_md5

The following example shows how to handle the result of a get:

pusher
  .get({ path: "/channels", params: {} })
  .then(response => {
    if (response.status !== 200) {
      throw Error("unexpected status")
    }
    // Parse the response body as JSON
    return response.json()
  )
  .then(body => {
    const channelsInfo = body.channels
    // Do something with channelsInfo
  })
  .catch(error => {
    // Handle error
  })
})

Get the list of channels in an application

pusher.get({ path: "/channels", params: params })

Information on the optional params and the structure of the returned JSON is defined in the REST API reference.

Get the state of a channel

pusher.get({ path: "/channels/[channel_name]", params: params })

Information on the optional params option property and the structure of the returned JSON is defined in the REST API reference.

Get the list of users in a presence channel

pusher.get({ path: "/channels/[channel_name]/users" })

The channel_name in the path must be a presence channel. The structure of the returned JSON is defined in the REST API reference.

WebHooks

The library provides a simple helper for WebHooks, which can be accessed via Pusher instances:

const webhook = pusher.webhook(request)

Requests must expose following fields:

  • headers - object with request headers indexed by lowercase header names
  • rawBody - string with the WebHook request body

Since neither Node.js nor express provide the body in the request, your application needs to read it and assign to the request object. See examples/webhook_endpoint.js for a simple webhook endpoint implementation using the express framework.

Headers object must contain following headers:

  • x-pusher-key - application key, sent by Channels
  • x-pusher-signature - WebHook signature, generated by Channels
  • content-type - must be set to application/json, what Channels does

After instantiating the WebHook object, you can use its following methods:

isValid

Validates the content type, body format and signature of the WebHook and returns a boolean. Your application should validate incoming webhooks, otherwise they could be faked.

Accepts an optional parameter containing additional application tokens (useful e.g. during migrations):

const webhook = pusher.webhook(request)
// will check only the key and secret assigned to the pusher object:
webhook.isValid()
// will also check two additional tokens:
webhook.isValid([
  { key: "x1", secret: "y1" },
  { key: "x2", secret: "y2" },
])

getData

Returns the parsed WebHook body. Throws a Pusher.WebHookError if the WebHook is invalid, so please check the isValid result before accessing the data.

// will return an object with the WebHook data
webhook.getData()

Please read the WebHooks documentation to find out what fields are included in the body.

getEvents

Returns events included in the WebHook as an array. Throws a Pusher.WebHookError if the WebHook is invalid, so please check the isValid result before accessing the events.

// will return an array with the events
webhook.getEvents()

getTime

Returns the Date object for the time when the WebHook was sent from Channels. Throws a Pusher.WebHookError if the WebHook is invalid, so please check the isValid result before accessing the time.

// will return a Date object
webhook.getTime()

Generating REST API signatures

If you wanted to send the REST API requests manually (e.g. using a different HTTP client), you can use the createSignedQueryString method to generate the whole request query string that includes the auth keys and your parameters.

pusher.createSignedQueryString({
  method: "POST", // the HTTP request method
  path: "/apps/3/events", // the HTTP request path
  body: '{"name":"foo","channel":"donuts","data":"2-for-1"}', // optional, the HTTP request body
  params: {}, // optional, the query params
})

The params object can't contain following keys, as they are used to sign the request:

  • auth_key
  • auth_timestamp
  • auth_version
  • auth_signature
  • body_md5

Testing

The tests run using Mocha. Make sure you've got all required modules installed:

npm install

Running the local test suite

You can run local integration tests without setting up a Pusher Channels app:

npm run local-test

Running the complete test suite

In order to run the full test suite, first you need a Pusher Channels app. When starting mocha, you need to set the PUSHER_URL environment variable to contain your app credentials, like following:

PUSHER_URL='http://KEY:[email protected]/apps/APP_ID' npm test

Credits

This library is based on the work of:

  • Christian Bäuerlein and his library pusher.
  • Jaewoong Kim and the node-pusher library.

License

This code is free to use under the terms of the MIT license.

pusher-http-node's People

Contributors

benw-pusher avatar bfischer1121 avatar callum-oakley avatar crossbreeze avatar danielrbrowne avatar danielwaterworth avatar deeborania avatar dependabot[bot] avatar fbenevides avatar freezy avatar jackfranklin avatar jameshfisher avatar jpatel531 avatar kashif avatar lafikl avatar leesio avatar leggetter avatar lukabratos avatar mdpye avatar mortonfox avatar pl avatar provstevi avatar pusher-ci avatar samuelyallop-pusher avatar sonologico avatar teddynecsoiu avatar topliceanu avatar vivangkumar avatar willsewell avatar zimbatm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pusher-http-node's Issues

TypeError: Not a buffer error in token.js

Hi, we're seeing an error with the latest version of Pusher - this happens when we do a Pusher.trigger on a public channel. It seems do have something to do with the changes in token.js.

TypeError: Not a buffer
at new Hmac (crypto.js:257:17)
at Object.Hmac (crypto.js:255:12)
at Token.sign (/Users/rhan/Projects/hgapp/node_modules/pusher/lib/token.js:22:17)
at createSignedQueryString (/Users/rhan/Projects/hgapp/node_modules/pusher/lib/requests.js:69:45)
at Object.send (/Users/rhan/Projects/hgapp/node_modules/pusher/lib/requests.js:20:21)
at Pusher.post (/Users/rhan/Projects/hgapp/node_modules/pusher/lib/pusher.js:155:12)
at Object.trigger (/Users/rhan/Projects/hgapp/node_modules/pusher/lib/events.js:10:10)
at Pusher.trigger (/Users/rhan/Projects/hgapp/node_modules/pusher/lib/pusher.js:138:10)
at PerformCardUpdated (/Users/rhan/Projects/hgapp/hgnode/util/PusherManager.js:207:23)
at /Users/rhan/Projects/hgapp/hgnode/services/PerformanceService.js:2332:31

ImportError No module named ndg.httpsclient.ssl_peer_verification`

After installing pusher into a specific folder with pip install -t directory pusher

I try a basic trigger to my app and get this.

File "deploy/lambda.py", line 5, in
pusher = Pusher(app_id=u'****', key=u'**', secret=u'***')
File "/home/vagrant/Code/Lamdba/DevPitch/deploy/pusher/pusher.py", line 42, in init
from pusher.requests import RequestsBackend
File "/home/vagrant/Code/Lamdba/DevPitch/deploy/pusher/requests.py", line 12, in
import urllib3.contrib.pyopenssl
File "/home/vagrant/Code/Lamdba/DevPitch/deploy/urllib3/contrib/pyopenssl.py", line 49, in
from ndg.httpsclient.ssl_peer_verification import SUBJ_ALT_NAME_SUPPORT
ImportError: No module named ndg.httpsclient.ssl_peer_verification`

Messages arrive out of order bug?

I am using this library to send log lines of my application via pusher.trigger, each line of a log is a separate event. The problem is that the log lines arrive out of order. I have assigned a line number index to each object in the event and I can see on the pusher debug console that they all arrive out of order. Even when I batch my log lines into 10 lines each they still arrive out of order.

README out of date

Now that parse.js is prebuilt the README is out of date.

I'm happy to fix this, but just putting this here so I don't forget.

Node.Js API Running on Docker

I have a Node.Js Api exposing several endpoints and methos to crud a MongoDB database. I also triggers pusher channel.
It works perfectly fine on my machine but when I put it inside a docker everything works ok but the pusher trigger never occurs, the console log shows no error, but the pusher console shows no requests, even the debug console on pusher shows me the request from the API running on the hw, but nothing happend when I run it inside Docker.
Is any special consideration I should have to run a node.js api inside docker?
Some comments
A curl to http://api.pusherapp.com/ inside docker works fine.
A ping to anywhere on internet from the docker replies ok.
The front end can call the dockerize api an the get, post and patch methods can crud on the mongodb without any issue.
The only thing that's not working are the pusher.trigger calls.

Thanks in advanced

PS: The code of the API is here https://gitlab.com/tfg-gastonvaldes/node-api-mongo-home

Outdated request dependency introduces security vulnerability

I ran the nsp package against my project and it reported a vulnerability with this library:

(+) 1 vulnerabilities found
┌───────────────┬───────────────────────────────────────────────────────┐
│               │ Regular Expression Denial of Service                  │
├───────────────┼───────────────────────────────────────────────────────┤
│ Name          │ hawk                                                  │
├───────────────┼───────────────────────────────────────────────────────┤
│ Installed     │ 1.1.1                                                 │
├───────────────┼───────────────────────────────────────────────────────┤
│ Vulnerable    │ < 3.1.3  || >= 4.0.0 <4.1.1                           │
├───────────────┼───────────────────────────────────────────────────────┤
│ Patched       │ >=3.1.3 < 4.0.0 || >=4.1.1                            │
├───────────────┼───────────────────────────────────────────────────────┤
│ Path          │ [email protected] > [email protected] > [email protected] > [email protected]  │
├───────────────┼───────────────────────────────────────────────────────┤
│ More Info     │ https://nodesecurity.io/advisories/77                 │
└───────────────┴───────────────────────────────────────────────────────┘

I noticed that if you upgrade to request v2.69.0, it depends on hawk 3.1.3, which is patched and does not have this vulnerability.

Promise support

It would be great if promises could be supported as alternatives to callbacks

Invalid channel Name exception

Hi,
Two days ago, newrelic catched the following error, so my server crashed.

[App:API][Err] Error: Invalid channel name: 's�ivctE-qervar�36�125'
   at validateChannel (/var/app/current/node_modules/pusher/lib/pusher.js:15:11)

_Note that i was filtering each input come to server._

Do you have any idea about the causes of this issue?.
Thank you.

Pusher constructor support for `cluster` option

A new cluster option should be available for the Pusher constructor.
When cluster is present, the host option changes into api-cluster.pusher.com.
When host option is present, it overrides all other options.
The behavior of Pusher.forCluster does not change, if by mistake an optional cluster is supplied, it will get overridden.

TypeScript build error - no changes

I haven't made any changes anywhere in the code. I'm starting a fresh project from:
https://github.com/microsoft/TypeScript-Node-Starter

I see this in the readme but not entirely sure what it means:

All external APIs should have types in index.d.ts.

so i defined my own /types/pusher/index.d.ts and declared namespaces below.

but i can't figure out how to resolve error TS2456: Type alias 'Response' circularly references itself.

has anybody had this issue?

typescript build error

node_modules/pusher/index.d.ts:50:18 - error TS2694: Namespace 'http' has no exported member 'Agent'.

50     agent?: http.Agent
                    ~~~~~

node_modules/pusher/index.d.ts:138:40 - error TS2503: Cannot find namespace 'request'.

138     constructor(token: Token, request: request.Request)
                                           ~~~~~~~

node_modules/pusher/index.d.ts:148:15 - error TS2456: Type alias 'Response' circularly references itself.

148   export type Response = Response
                  ~~~~~~~~


Found 3 errors.

Any interest in refactoring to ES2015?

Hi 👋

Do you have any interest in refactoring pusher-http-node to use ES2015? I was reading the source code and noticed a few opportunities to improve readability with template literals, default parameters, etc.

I understand that you'll probably want to maintain compatibility with Node >=0.8.0 so transpilation will be necessary.

Transpilation does come at a cost to simplicity and - in some cases - ease of debugging, so I'll understand if it isn't worth it to you. That being being said, if it is something you're interested in, I would like to help! From what I can tell, you have a solid set of tests so it should be possible to avoid regressions 👍.

Add support to listen to events as well

I'd like suggest/discuss to add subscribe & bind support to this package as well.

In a microservice world, services are both triggering and listening to events, even if clients may don't. See
http://microservices.io/patterns/communication-style/messaging.html
http://microservices.io/patterns/data/saga.html
https://www.nginx.com/blog/event-driven-data-management-microservices/
etc.

I'm aware that I can use pusher-js for this also in Node, but why handle 2 packages and have two separate clients (even though its not hard) if I could also have it in one?

Impossible to execute a get request

When I try to get channels list, I've got this error:

_http_outgoing.js:333
throw new Error('"name" and "value" are required for setHeader().');
^
Error: "name" and "value" are required for setHeader().
at ClientRequest.OutgoingMessage.setHeader (_http_outgoing.js:333:11)
at new ClientRequest (_http_client.js:101:14)
at Object.exports.request (http.js:49:10)
at Request.start (/var/www/WEB/tuborg_push/node_modules/pusher/node_modules/request/request.js:812:30)
at Request.end (/var/www/WEB/tuborg_push/node_modules/pusher/node_modules/request/request.js:1494:28)
at end (/var/www/WEB/tuborg_push/node_modules/pusher/node_modules/request/request.js:550:16)
at /var/www/WEB/tuborg_push/node_modules/pusher/node_modules/request/request.js:564:9
at process._tickCallback (node.js:355:11)
at Function.Module.runMain (module.js:503:11)
at startup (node.js:129:16)

The code I try to execute is really simple:

var config = require('./config.js');
var Pusher = require('pusher');

var pusher = new Pusher({ appId: config.APP_ID, key: config.APP_KEY, secret: config.APP_SECRET });
pusher.get({ path: '/channels', params: {} }, function(error, request, response) {
if (response.statusCode === 200) {
var result = JSON.parse(response.body);
var channelsInfo = result.channels;
}
});

Node version : 0.12.1

Support Node version 10

At the moment the tests fail with Node 10, there's something about Buffer being deprecated, unsure whether that's related.

should error if callback is not function

this is bad error handling; it should blow up in this case rather than silently do nothing

function dispatchRequestResult(err, url, req, res, callback) {
  if (typeof callback !== "function") {
    return;
  }

Cant call .trigger() with callback without socketId

I just upgraded all my packages from my project and pusher-related code broke. It contained a lot of calls like: :
pusher.trigger( channel, event_name, data, handlePushErr )
I looked into the source, index.js line 122. I'm no expert but, I think that would fix it :
if( typeof socketId == "function") { callback = socketId; socketId = null; }
in order to allow the use of a callback without socketId ?

Encrypted channel not working

When trying to use encrypted channels I get this error

Error: Cannot generate shared_secret because encryptionMasterKey is not set

I setup the instance like this

new Pusher({
      appId: '...',
      key: '...',
      secret: '...',
      cluster: 'eu',
      useTLS: true,
      encryptionMasterKeyBase64: 'HOeaw50duhaSgyUkcTYgq11TiSiGmUbwFoPXZ4Uud34=',
    });

Error: socket hang up

Hi - As of this morning, my code started failing. It was working early Sunday morning when I last tested.

const Feeds = require("pusher-feeds-server");
const feeds = new Feeds({
  instanceLocator: "[valid instance locator]",
  key: "[valid key]",
});
feeds.publish("message", {
  message: "Hello from the server!",
})
.catch(function (err) {
 // no clue if this is how we catch errors 
 console.log(err);
});

Node.js console output:

(node:31160) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
(node:31160) UnhandledPromiseRejectionWarning: Error: socket hang up
at createHangUpError (_http_client.js:331:15)
at TLSSocket.socketOnEnd (_http_client.js:423:23)
at emitNone (events.js:111:20)
at TLSSocket.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1064:12)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
at process._tickCallback (internal/process/next_tick.js:180:9)
(node:31160) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)

npm -v

6.4.1

node -v

v8.11.4

Silent failure on authorize when socket === undefined

I had a regression issue where the signature was being miscalculated due to a bug where I was passing undefined as the socket id

If the authenticate method gives a warning or hard failure when the socket id argument is not defined that might prevent others from running into this

Documentation states pusher.auth when pusher.authenticate should be used

I think this has changed at some point but many guides and the actual documentation of this module still refer to the "auth" function, which at the current state does not exist.

I think it might be best to make the "auth" an alias to "authenticate" so that all implementations don't magically break when the version updates happen.

nsp check fails due to vulnerability in tough-cookie dependency

Vulnerability reported by https://nodesecurity.io/

Run:

nsp check

Current behaviour:

┌───────────────┬───────────────────────────────────────────────────────┐
│               │ ReDoS via long string of semicolons                   │
├───────────────┼───────────────────────────────────────────────────────┤
│ Name          │ tough-cookie                                          │
├───────────────┼───────────────────────────────────────────────────────┤
│ Installed     │ 2.2.2                                                 │
├───────────────┼───────────────────────────────────────────────────────┤
│ Vulnerable    │ >=0.9.7 <=2.2.2                                       │
├───────────────┼───────────────────────────────────────────────────────┤
│ Patched       │ >=2.3.0                                               │
├───────────────┼───────────────────────────────────────────────────────┤
│ Path          │ [email protected] > [email protected] > [email protected]│
├───────────────┼───────────────────────────────────────────────────────┤
│ More Info     │ https://nodesecurity.io/advisories/130                │
└───────────────┴───────────────────────────────────────────────────────┘

Expected/desired behavior:

(+) No known vulnerabilities found

installation instructions not working

I ran:
$ npm install pusher --prefix cloud/modules
After that the instructions say to run:
$ cd cloud/modules/pusher

Unfortunately, there is no cloud/modules/pusher folder, there is
cloud/modules/node_modules/pusher

Tried cd into that folder and run:
$ npm run parse-build

It blows up with following trace:
DsMacBookPro:pusher dmitry$ npm run parse-build

[email protected] parse-build /Users/dmitry/hacks/tentags/TenTags/cloud/modules/node_modules/pusher
echo 'Creating build for Parse Cloud.' && node ./node_modules/.bin/webpack --config=./parse.webpack.js

Creating build for Parse Cloud.
module.js:327
throw err;
^

Error: Cannot find module '/Users/dmitry/hacks/tentags/TenTags/cloud/modules/node_modules/pusher/node_modules/.bin/webpack'
at Function.Module._resolveFilename (module.js:325:15)
at Function.Module._load (module.js:276:25)
at Function.Module.runMain (module.js:429:10)
at startup (node.js:139:18)
at node.js:999:3

npm ERR! Darwin 15.2.0
npm ERR! argv "/usr/local/Cellar/node/5.3.0/bin/node" "/usr/local/bin/npm" "run" "parse-build"
npm ERR! node v5.4.1
npm ERR! npm v3.3.12
npm ERR! code ELIFECYCLE
npm ERR! [email protected] parse-build: echo 'Creating build for Parse Cloud.' && node ./node_modules/.bin/webpack --config=./parse.webpack.js
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] parse-build script 'echo 'Creating build for Parse Cloud.' && node ./node_modules/.bin/webpack --config=./parse.webpack.js'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the pusher package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! echo 'Creating build for Parse Cloud.' && node ./node_modules/.bin/webpack --config=./parse.webpack.js
npm ERR! You can get their info via:
npm ERR! npm owner ls pusher
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR! /Users/dmitry/hacks/tentags/TenTags/cloud/modules/node_modules/pusher/npm-debug.log
DsMacBookPro:pusher dmitry$ pwd
/Users/dmitry/hacks/tentags/TenTags/cloud/modules/node_modules/pusher
DsMacBookPro:pusher dmitry$

Please help!

passing a callback to the trigger function causes an error

using the trigger function with a callback throw an error

Error: Invalid socket id: 'function (err) {
                console.log(err);
                done(err);
            }'
      at validateSocketId /node_modules/pusher/lib/pusher.js:24:11)
      at Pusher.trigger (/node_modules/pusher/lib/pusher.js:123:5)
          pusher.trigger('test_channel', 'my_event', {
                "message": "hello world"
            }, function(err){
                console.log(err);
                done(err);
            });

Guard against undefined key

If secret is undefined and we call Pusher.prototype.trigger, an ambiguous error is thrown:

var pusher = new Pusher({
  appId: process.env.APP_ID
  key: undefined,
  secret: process.env.SECRET
  encrypted: true
})
pusher.trigger(...)

crypto.js:84
this._handle.init(hmac, toBuf(key));
^
TypeError: Key must be a buffer
at TypeError (native)
at new Hmac (crypto.js:84:16)
at Object.Hmac (crypto.js:82:12)
at Token.sign (/home/booker/Code/pusher-experiment/node_modules/pusher/lib/token.js:24:17)
at createSignedQueryString (/home/booker/Code/pusher-experiment/node_modules/pusher/lib/requests.js:72:45)
at Object.send (/home/booker/Code/pusher-experiment/node_modules/pusher/lib/requests.js:20:21)
at Pusher.post (/home/booker/Code/pusher-experiment/node_modules/pusher/lib/pusher.js:168:12)
at Object.exports.trigger (/home/booker/Code/pusher-experiment/node_modules/pusher/lib/events.js:10:10)
at Pusher.trigger (/home/booker/Code/pusher-experiment/node_modules/pusher/lib/pusher.js:138:10)
at Object. (/home/booker/Code/pusher-experiment/index.js:4:8)

secret could be undefined because of a configuration error:

var pusher = new Pusher({
  appId: process.env.APP_ID
  key: process.env.KEY, // What if process.env.KEY is undefined?
  secret: process.env.SECRET
  encrypted: true
})

secret might also be undefined if someone confuses the API (as I did 😞):

var pusher = new Pusher( process.env.APP_ID, 'd55447385c490cb7e41a', 'dbd6cec9e5dceac384dc');

(In haste, I mistakenly passed individual arguments to Pusher when I should have passed a parameter object. This resulted in secret being undefined and the "Key must be a buffer" error being thrown.)

What do you think about adding a guard clause - like the one for Pusher.prototype.authenticate - that ensures secret is truthy? Something like this:

if (!secret) {
  throw new Error('You did not pass a valid secret to the Pusher constructor function.')
}

This way, if someone - for whatever reason - does not specify a secret, the error will at least point to the problem, helping the user fall into the pit of success.

Example of using `trigger` callback

It looks like the trigger method accepts a callback which accepts the results of the trigger:

exports.trigger = function(pusher, channels, eventName, data, socketId, callback) {

This callback is important for debugging, and for cases where the user needs to trigger events in sequence.

However I can't see any usage examples in the README.

Pusher trigger not working inside the heroku server

My pusher works fine on heroku and it triggers the event locally.
But if I deploy it to my heroku sever, it actually doesn't work.
I am working on Node - Express, however, I suppose this issues doesn't come from the framework.

Is there any other configuration which I am missing currently?

[email protected]: request has been deprecated

When installing pusher via npm presents this WARN:

$ npm install pusher
npm WARN deprecated [email protected]: request has been deprecated, see https://github.com/request/request/issues/3142
+ [email protected]

Then an import of Pusher var:

ERROR in ./node_modules/request/lib/har.js
Module not found: Error: Can't resolve 'fs' in '/Users/oscar/Project/node_modules/request/lib'
 @ ./node_modules/request/lib/har.js 3:9-22
 @ ./node_modules/request/request.js
 @ ./node_modules/request/index.js
 @ ./node_modules/pusher/lib/requests.js
 @ ./node_modules/pusher/lib/pusher.js

The github issue 3142 not presents any solution currently :(

Package.json From NPM Doesn't Match Master

When I install the latest version 1.2.1 the package.json is quite different to what is on the master branch. The main problem is that webpack is still a main dependency but there seems to be a load of stuff related to pusher-rest-node too for some reason.

{
  "name": "pusher",
  "description": "Node.js client to interact with the Pusher REST API",
  "version": "1.2.1",
  "author": {
    "name": "Pusher",
    "email": "[email protected]"
  },
  "contributors": [
    {
      "name": "fabrik42",
      "email": "[email protected]"
    },
    {
      "name": "Jaewoong Kim",
      "email": "[email protected]"
    },
    {
      "name": "Phil Leggetter",
      "email": "[email protected]"
    },
    {
      "name": "Paweł Ledwoń",
      "email": "[email protected]"
    }
  ],
  "dependencies": {
    "request": "=2.67.0",
    "webpack": "^1.12.9"
  },
  "devDependencies": {
    "mocha": "=1.20.1",
    "expect.js": "=0.3.1",
    "sinon": "=1.10.2",
    "nock": "=0.28.0",
    "express": "=3.11.0"
  },
  "optionalDependencies": {
    "webpack": "^1.12.9"
  },
  "scripts": {
    "test": "node node_modules/.bin/mocha tests/integration/**/*.js",
    "parse-build": "echo 'Creating build for Parse Cloud.' && node ./node_modules/.bin/webpack --config=./parse.webpack.js"
  },
  "keywords": [
    "pusher",
    "websockets",
    "realtime"
  ],
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "git://github.com/pusher/pusher-rest-node.git"
  },
  "main": "lib/pusher",
  "engines": {
    "node": ">= 0.8.0"
  },
  "gitHead": "1fd150f05c02498b6084605ffa5b3b882212d841",
  "bugs": {
    "url": "https://github.com/pusher/pusher-rest-node/issues"
  },
  "homepage": "https://github.com/pusher/pusher-rest-node#readme",
  "_id": "[email protected]",
  "_shasum": "58b8c406e34373b7f46579854c445d09e2eacd6b",
  "_from": "[email protected]",
  "_npmVersion": "3.3.12",
  "_nodeVersion": "5.4.1",
  "_npmUser": {
    "name": "alexandru.topliceanu",
    "email": "[email protected]"
  },
  "dist": {
    "shasum": "58b8c406e34373b7f46579854c445d09e2eacd6b",
    "tarball": "https://registry.npmjs.org/pusher/-/pusher-1.2.1.tgz"
  },
  "maintainers": [
    {
      "name": "alexandru.topliceanu",
      "email": "[email protected]"
    },
    {
      "name": "pusherapp",
      "email": "[email protected]"
    },
    {
      "name": "zimbatm",
      "email": "[email protected]"
    }
  ],
  "_npmOperationalInternal": {
    "host": "packages-13-west.internal.npmjs.com",
    "tmp": "tmp/pusher-1.2.1.tgz_1457015762453_0.7557593856472522"
  },
  "directories": {},
  "_resolved": "https://registry.npmjs.org/pusher/-/pusher-1.2.1.tgz",
  "readme": "ERROR: No README data found!"
}

Can't get user count in presence channel

pusher.get({
  path: '/channels/presence-' + channelQueryName + '/users',
  params: {
    info: 'user_count'
  }
}, function(err, req, res) {
  debug('presence', res.body); // -> output: The following query string parameters are extraneous: info
});

cant trigger pusher ?

I'm trying pusher trigger but i'm getting this error invalid channel name. I hope you guys can help me
invalidchannel
invalidchannel

Crash on get request (node 12.x)

_http_outgoing.js:333
    throw new Error('"name" and "value" are required for setHeader().');
          ^
Error: "name" and "value" are required for setHeader().
    at ClientRequest.OutgoingMessage.setHeader (_http_outgoing.js:333:11)
    at new ClientRequest (_http_client.js:101:14)
    at Object.exports.request (http.js:49:10)
    at Request.start (c:\gdrive\dev\townsquared\trunk\server\notifications\node_modules\pusher\node_modules\request\request.js:812:30)
    at Request.end (c:\gdrive\dev\townsquared\trunk\server\notifications\node_modules\pusher\node_modules\request\request.js:1494:28)
    at end (c:\gdrive\dev\townsquared\trunk\server\notifications\node_modules\pusher\node_modules\request\request.js:550:16)
    at c:\gdrive\dev\townsquared\trunk\server\notifications\node_modules\pusher\node_modules\request\request.js:564:9
    at process._tickDomainCallback (node.js:381:11)

Bug is there:

 /lib/requests.js

  handler[options.method.toLowerCase()]({
    url: url,
    proxy: config.proxy,
    timeout: config.timeout,
    headers: {
      // in case 'content-type' is undefined request.setHeader() will crash app
      'content-type': (body ? 'application/json' : undefined) 
    },
    body: body
  }, function(err, res, resBody) {
    dispatchRequestResult(err, url, this.req, res, callback);
  });

This is fixed version:

    var params = {
        url: url,
        proxy: config.proxy,
        timeout: config.timeout
    };

    if (body) {
        params.headers = {'content-type': 'application/json'};
        params.body = body;
    }

    handler[options.method.toLowerCase()](params, function(err, res, resBody) {
        dispatchRequestResult(err, url, this.req, res, callback);
    });

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.