Where do I handle feathersjs/socketio-client connection error - socket.io

I'm using feathers with socketio in backend. The client is listening and everything works well.
I want to handle the 'server not responding' error and I don't find where can I do that?
The error thrown by the server:
"Unhandled promise rejection
Object { type: "FeathersError", name: "Timeout", message: "Timeout of 5000ms exceeded calling find on newsfeed", code: 408, className: "timeout", data: {…}, errors: {}, stack: "FeathersError#webpack-internal:///./node_modules/#feathersjs/errors/lib/index.js:58:19\nTimeout#webpack-internal:///./node_modules/#feathersjs/errors/lib/index.js:135:3\nsend/</timeoutId<#webpack-internal:///./node_modules/#feathersjs/transport-commons/lib/client.js:66:9\n" }"
It is correct, the 'promise' is not handled! Where do I handle?
I tried adding catch on each line just to see what works but without success:
import feathers from '#feathersjs/feathers'
import socketio from '#feathersjs/socketio-client'
import io from 'socket.io-client'
const socket = io('http://localhost:3030/', {transports: ['websocket']});
socket.on("connect_failed", er=>console.error('Error connecting to server: ', er));
const restApi = feathers()
.configure(socketio(socket));
try {
restApi.service('/newsfeed');
restApi.on("connect_failed", er=>console.error('Error connecting to server: ', er));
}
catch (er) {
console.error('Error connecting to server: ', er)
}
export default restApi

The timeout error is coming from a particular request so you have to handle it wherever you are making the request.
restApi.service('/newsfeed').find()
If you're using async/await, you can wrap your service call in a try/catch or my personal favorite is just putting a catch on the call;
// try/catch
try {
const response= await restApi.service('/newsfeed').find();
catch(e) {
// handle e
}
//just use catch
const response= await restApi.service('/newsfeed').find().catch(e => {
// handle e
});
If you're using promises, just use a catch:
restApi.service('/newsfeed').find().then(response => {
// handle response
}).catch(e => {
// handle e
});

Related

NestJs socket authentication, emit event in handleConnection

Upon failed authentication, before disconnecting, I want to emit an event to the client informing that the token provided with the request is invalid. In my WebSocketGateway this is my code:
handleConnection(client: Socket, ...args: any[]) {
try {
this.socketAuthService.authenticate(client);
this.logger.log(`Client connected: ${client.id}`);
} catch (e) {
this.logger.error(`Client ${client.id} tried to connect with invalid token`);
client.emit('unauthorized', 'Invalid Token');
client.disconnect();
this.logger.log(`Client disconnected due to invalid token: ${client.id}`);
}
}
My client:
this.socket.on('unauthorized', (msg) => {
console.log(msg);
});
The event is not sent / received. Any idea?
Cheers
What you need is to close the socket with a custom socket error code and a message. You can do this by using socket.close(code, message);
socket.close(4004, "Unauthorized Request");
You will get an exception like this
Postman exception on websockets invalid origin

"[Network] undefined" when trying to use subscriber - URQL

I am trying to set up a subscriber to log some output on the creation of a new Message.
Currently using Urql, with ApolloServerExpress on the backend.
I am receiving an error from the useSubscription method which I am logging to the console :
message: "[Network] undefined"
name: "CombinedError"
I know for sure my backend is working as I can subscribe using the Graphiql playground just fine.
As far as front end goes, I have followed almost exactly as the example in the Urql docs.
WS Client:
const wsClient = createWSClient({
url: "ws://localhost:4000/graphql",
});
Subscriber Exchange:
subscriptionExchange({
forwardSubscription(operation) {
return {
subscribe: (sink) => {
const dispose = wsClient.subscribe(operation, sink);
return {
unsubscribe: dispose,
};
},
};
},
}),
MessageList Component:
const newMessages = `
subscription Messages {
newMessage {
content
status
sender {
id
email
}
recipient {
id
email
}
}
}
`;
...
const handleSub = (messages: any, newMessage: any) => {
console.log("Messages: ", messages);
console.log("newMessages: ", newMessage);
};
const [res] = useSubscription({ query: newMessages }, handleSub);
console.log("Res: ", res);
I was getting the same error when using subscriptions with urql. In my case, I was able to do console.log(error.networkError); which gave a much more helpful error message than [Network] undefined.
You can read more about errors in urql here.
The error I got from error.networkError was:
Event {
"code": 4400,
"isTrusted": false,
"reason": "{\"server_error_msg\":\"4400: Connection initialization failed: Missing 'Authorization' or 'Cookie' header in JWT authenticati",
}
I was able to fix it by adding authentication to my subscription exchange setup. Here's the code I'm using now:
const wsClient = createWSClient({
url: "wss://your-api-url/graphql",
connectionParams: async () => {
// Change this line to however you get your auth token
const token = await getTokenFromStorage();
return {
headers: {
Authorization: `Bearer ${token}`,
},
};
},
});
Ended up chalking graphql-ws and switched over to subscriptions-transport-ws.
Fixed my issues.

Coinbase-pro for Node.js - Websocket connection breaking with error: read ECONNRESET

I'm currently stuck with an issue I'm getting with the coinbase-pro-node npm package (https://github.com/coinbase/coinbase-pro-node). I'm connecting to the matches channel and listening for messages there but the connection with the Websocket breaks after a few hours without telling me much. I can't trace back the problem and it doesn't happen on the same intervals. Sometimes it breaks just minutes after I run the script. Thanks for the help.
The code:
const CoinbasePro = require('coinbase-pro');
var coinbaseWs = '';
function connect() {
coinbaseWs = new CoinbasePro.WebsocketClient(
['BTC-USD'],
'wss://ws-feed.pro.coinbase.com',
{
key: 'xxxx',
secret: 'xxxx',
passphrase: 'xxxx',
},
{ channels: ['matches'] }
);
coinbaseWs.on('message', async data => {
console.log(data)
});
coinbaseWs.on('error', err => {
console.error("Connection with Coinbase websocket failed with error: " + err);
console.log("Error stack trace: " + err.stack);
});
coinbaseWs.on('close', () => {
console.error("Connection with Coinbase websocket closed!");
});
}
connect();
Error stack:
Error: read ECONNRESET
File "internal/stream_base_commons.js", line 167, in TLSWrap.onStreamRead
it does break from time to time for no apparent reason. All you can do is listen for the heartbeat messages and use those to decide whether to re-initiate a new websocket feed. I raised a similar query directly with the coinbase pro/gdax customer support.

When would this Koajs error happen

I'm trying to get my head around Koa and I am making small progress. At the moment I think I understand this code
import Koa from 'koa';
import router from './router';
const app = new Koa();
app.use(async (ctx, next) => {
try {
await next();
} catch (err) {
ctx.body = { message: err.message };
ctx.status = err.status || 500;
}
});
app.use(router.routes());
app.listen(3000);
export default app;
Instead of having a callback to handle the error, we go upstream to that catch. But I would like to make the above error execute.
How can I simulate an error
If you have an unhandled error in your upstream code, THEN this error here would fire.
To simulate an error do :
throw new Error('error message')

Preventing a 'heartbeat timeout' with websockets and SocketIO

I am using NodeJS and SocketIO for my websocket solution. It works fine, but after a few minutes, my socket server always times out with the following messages in my console:
debug - fired heartbeat timeout for client
info - transport end <heartbeat timeout>
debug - set close timeout for client
debug - cleared close timeout for client
debug - discarding transport
Here is my complete server.js file:
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
app.listen(3000);
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'from socket server' });
socket.on('swipe', function (from, msg) {
console.log('I received a private message by ', from, ' saying ', msg);
socket.emit('swipe event received on server!');
});
How can I prevent the timeouts from happening?
Check out the close timeout and heartbeat timeout options here
You can set these programmatically on the server via:
var io = require('socket.io').listen(80);
io.set('close timeout', 60);
io.set('heartbeat timeout', 60);
As for the design of your application, you should check out this question for whether or not you should change the timeout.

Resources