Websockets crash when messaging a twit stream
version: 3.0.0
Node.js version(s): 8.1.0
Express version(s): 4.14.1
OS version(s): Mac OSX Sierra
App.js
'use strict';
const express = require('express');
const app = express();
const http = require('http')
const Twit = require('twit')
const WebSocket = require('ws');
const port = 3000;
require('dotenv').config()
const server = http.createServer(app);
const tweets = new WebSocket.Server({ server, path:'/tweets' });
const trump = new WebSocket.Server({ server, path:'/trump' });
var T = new Twit({
consumer_key: process.env.TWITTER_CONSUMER_KEY,
consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
access_token: process.env.TWITTER_ACCESS_TOKEN,
access_token_secret: process.env.TWITTER_ACCESS_SECRET,
})
app.get('/', function(req, res) {
res.send('Congratulations, you sent a GET request!');
console.log('Received a GET request and sent a response');
});
app.use(function (req, res, next) {
console.log('middleware');
req.testing = 'testing';
return next();
});
app.get('/', function(req, res, next){
console.log('get route', req.testing);
res.end();
});
tweets.on('connection', function(ws, req) {
ws.on('connect', function(req) {
console.log(req)
ws.send(req);
});
const stream = T.stream('statuses/filter', { track: ['POTUS', 'trump', 'president', 'realDonaldTrump'] })
stream.on('tweet', function(tweet){
console.log(tweet)
ws.send(tweet)
})
})
trump.on('connection', function(ws, req) {
const stream = T.stream('statuses/user_timeline', { screen_name: ['POTUS', 'realDonaldTrump'] })
stream.on('tweet', function(tweet) {
console.log(tweet)
ws.send(tweet)
})
})
server.listen(port, function listening() {
console.log('Listening on %d', server.address().port);
});
Bin
(() => {
const APP = require('../app.js');
})();
The stream doesn't crash, the connection stays established and tweets are sent to the clients that are connected.
The stream crashes after one tweet fires.
Listening on 3000
{ created_at: 'Thu Jun 22 23:29:34 +0000 2017',
id: 878032244194934800,
id_str: '878032244194934784',
text: '@realDonaldTrump Really? Sure doesn\'t feel like it. Majority of THE ENTIRE WORLD CAN\'T STAND YOU!',
display_text_range: [ 17, 97 ],
source: '<a href="http://twitter.com/download/android" rel="nofollow">Twitter for Android</a>',
truncated: false,
in_reply_to_status_id: 878027873650475000,
in_reply_to_status_id_str: '878027873650475008',
in_reply_to_user_id: 25073877,
in_reply_to_user_id_str: '25073877',
in_reply_to_screen_name: 'realDonaldTrump',
user:
{ id: 31005891,
id_str: '31005891',
name: 'Hoozshee',
screen_name: 'mrsmojorisin93',
location: 'La La Land, Kansas ',
url: null,
description: 'Not your typical human.... 馃嚭馃嚫鉂ゐ焽吼焽糕潳馃嚭馃嚫',
protected: false,
verified: false,
followers_count: 12,
friends_count: 50,
listed_count: 0,
favourites_count: 917,
statuses_count: 46,
created_at: 'Tue Apr 14 00:32:41 +0000 2009',
utc_offset: -18000,
time_zone: 'America/Chicago',
geo_enabled: false,
lang: 'en',
contributors_enabled: false,
is_translator: false,
profile_background_color: 'C0DEED',
profile_background_image_url: 'http://abs.twimg.com/images/themes/theme1/bg.png',
profile_background_image_url_https: 'https://abs.twimg.com/images/themes/theme1/bg.png',
profile_background_tile: false,
profile_link_color: '1DA1F2',
profile_sidebar_border_color: 'C0DEED',
profile_sidebar_fill_color: 'DDEEF6',
profile_text_color: '333333',
profile_use_background_image: true,
profile_image_url: 'http://pbs.twimg.com/profile_images/875336526338641922/Ob4qCgLT_normal.jpg',
profile_image_url_https: 'https://pbs.twimg.com/profile_images/875336526338641922/Ob4qCgLT_normal.jpg',
profile_banner_url: 'https://pbs.twimg.com/profile_banners/31005891/1490041984',
default_profile: true,
default_profile_image: false,
following: null,
follow_request_sent: null,
notifications: null },
geo: null,
coordinates: null,
place: null,
contributors: null,
is_quote_status: false,
retweet_count: 0,
favorite_count: 0,
entities:
{ hashtags: [],
urls: [],
user_mentions: [ [Object] ],
symbols: [] },
favorited: false,
retweeted: false,
filter_level: 'low',
lang: 'en',
timestamp_ms: '1498174174723' }
/Users/kylecameronryanfahey/Documents/Github/serverSentiment/node_modules/ws/lib/WebSocket.js:358
else throw new Error('not opened');
^
Error: not opened
at WebSocket.send (/Users/kylecameronryanfahey/Documents/Github/serverSentiment/node_modules/ws/lib/WebSocket.js:358:18)
at StreamingAPIConnection.<anonymous> (/Users/kylecameronryanfahey/Documents/Github/serverSentiment/app.js:52:8)
at emitOne (events.js:115:13)
at StreamingAPIConnection.emit (events.js:210:7)
at module.exports.<anonymous> (/Users/kylecameronryanfahey/Documents/Github/serverSentiment/node_modules/twit/lib/streaming-api-connection.js:319:56)
at emitOne (events.js:115:13)
at module.exports.emit (events.js:210:7)
at module.exports.Parser.parse (/Users/kylecameronryanfahey/Documents/Github/serverSentiment/node_modules/twit/lib/parser.js:47:16)
at Gunzip.<anonymous> (/Users/kylecameronryanfahey/Documents/Github/serverSentiment/node_modules/twit/lib/streaming-api-connection.js:139:21)
at emitOne (events.js:115:13)
at Gunzip.emit (events.js:210:7)
at addChunk (_stream_readable.js:250:12)
at readableAddChunk (_stream_readable.js:237:11)
at Gunzip.Readable.push (_stream_readable.js:195:10)
at Gunzip.Transform.push (_stream_transform.js:151:32)
at Zlib.callback (zlib.js:444:14)
I see two issues in your code. The first:
const tweets = new WebSocket.Server({ server, path:'/tweets' });
const trump = new WebSocket.Server({ server, path:'/trump' });
This no longer works. See https://github.com/websockets/ws/pull/885 for more info.
The second is that you should check that ws.readyState is OPEN before caling ws.send() or use a callback and handle possible errors that are passed to it.
Closing. Removing paths fixed it. The docs don't have mention of this but different stack overflow questions do.
I had the same problem when I am developing a customer websocket router based on express routing system.
Most helpful comment
I see two issues in your code. The first:
This no longer works. See https://github.com/websockets/ws/pull/885 for more info.
The second is that you should check that
ws.readyStateisOPENbefore calingws.send()or use a callback and handle possible errors that are passed to it.