KafkaJSConnectionError: Connection timeout. SSL configuration on Kafka.js - javascript

The credentials that I am provided with :- (I also have kafka.keystore.jks and kafka.truststore.jks)
host: xxxxx-xxxxx-x.cloudclusters.net
port: xxxxx
ip: xxx.xxx.xxx.xx
trustore pw: xxxxxxxx
keystore pw: xxxxxxxx
import WebSocket from 'ws';
import express from 'express'
import { Kafka } from 'kafkajs';
import { Partitioners } from 'kafkajs';
import jks from 'jks-js';
import fs from 'fs';
const keystore = jks.toPem(
fs.readFileSync('./kafka.keystore.jks'),
'mypassword'
);
const trustore = jks.toPem(
fs.readFileSync('./kafka.truststore.jks'),
'mypassword'
);
const {
caroot: {ca},
localhost: {key,cert} } = keystore;
// const { caroot: {ca} } = trustore;
console.log("**************** kafka.keystore.jks ****************");
// console.log(keystore)
console.log("ca ===>", ca); // getting the keys
console.log("key ===>", key);
console.log("cert ===>", cert);
console.log("**************** kafka.truststore.jks ****************");
// console.log(trustore)
// console.log("ca ===>", ca);
// setting up kafka
const kafka = new Kafka({
clientId: 'qa-topic',
brokers: ['xxxx.cloudclusters.net:xxxx'], // HOST:PORT
ssl: {
rejectUnauthorized: false,
ca: ca,
key: key,
cert: cert
},
})
const producer = kafka.producer({ createPartitioner: Partitioners.DefaultPartitioner })
producer.on('producer.connect', () => {
console.log(`KafkaProvider: connected`);
});
producer.on('producer.disconnect', () => {
console.log(`KafkaProvider: could not connect`);
});
producer.on('producer.network.request_timeout', (payload) => {
console.log(`KafkaProvider: request timeout ${payload.clientId}`);
});
await producer.connect().catch((e) => {
console.log("ERROR happened ==>",e) // Getting Connection Timeout Error
})
const port = process.env.PORT || 5000;
app.listen(port, () => {
console.log(`I am listening at ${port}`);
});
I am currently using SSL Configuration, following the Kafka.js Documentation. I have gotten ca,key,cert as strings from my kafka.keystore.jks. I am passing them in the SSL Object but when I try to connect my producer, I get the following error :-
cause: KafkaJSConnectionError: Connection timeout
at Timeout.onTimeout [as _onTimeout]

Related

mongoose fails to connect on first attempt

I'm using nodejs, express, and mongoose (6.9.0) on my app. It's deployed on Vercel, the first time I try to call to the api from my frontend app, the api shows me the following error on console
MongoDB disconnectedMongoose default connection has occured: MongooseServerSelectionError: Could not connect to any servers in your MongoDB Atlas cluster. One common reason is that you're trying to access the database from an IP that isn't whitelisted. Make sure your current IP address is on your Atlas cluster's IP whitelist: https://docs.atlas.mongodb.com/security-whitelist/
My api is wishlisted on MongoDB, and this only happens on the first call to the api, the next calls works perfectly. (this only happens in production)
This is my connect function
const { MONGO_DB_URI_TEST } = process.env;
const connectionString = MONGO_DB_URI_TEST;
const mongooseOptions = {
useUnifiedTopology: true,
useNewUrlParser: true,
};
if (!connectionString) {
console.error("Failed to import .env");
}
const connectMongo = () => {
mongoose.connect(connectionString, mongooseOptions);
mongoose.connection.on("connected", () => {
console.log("MongoDB is connected");
});
mongoose.connection.on("error", (error) => {
console.log(`Mongoose default connection has occured: ${error}`);
process.exit();
});
mongoose.connection.on("disconnected", () => {
console.log("MongoDB disconnected");
});
process.on("uncaughtException", () => {
mongoose.disconnect();
});
const closeConnection = function () {
mongoose.connection.close(() => {
console.log("MongoDB disconnected due to app termination");
process.exit(0);
});
};
process.on("SIGINT", closeConnection).on("SIGTERM", closeConnection);
};
export { connectMongo };
app.js (it has many middlewares irrelevant here)
const app = express();
connectMongo();
app.use("/", router);
export { app };
index.js
import { app } from "./src/app.js";
const PORT = process.env.PORT || 4000;
const server = app.listen(PORT, () => {
console.log("Server listening on port", PORT);
});
export default server;
How can I solve this? Thanks in advance.

How to send the req alongside the socket.io socket?

I have implemented a socket.io like this:
client:
const socket = io.connect(':4000');
socket.emit('trim-movie', data);
server:
const io = socket(server);
io.on("connection", (socket) => {
socket.on('trim-movie', (data) => trimMovie(data));
});
In order to authorize the user in the server I need the request (req) to be send with the socket right?
How can I do this?
[Try socket io middleware]
Sending credentials[1]
The client can send credentials with the auth option:
// plain object
const socket = io({
auth: {
token: "abc"
}
});
// or with a function
const socket = io({
auth: (cb) => {
cb({
token: "abc"
});
}
});
Those credentials can be accessed in the handshake object on the server-side:
io.use((socket, next) => {
const token = socket.handshake.auth.token;
// ...
});

Why my socketio is not connecting with my socketio-client?

i am working on a chatapp project that needs a real time chatting so i have used socketio in my server side which is written in nodejs and than used socketio-client in my main chatapp react-native project.
But now a problem is coming my socket is not initializing. I'm not able to connect my server with my main app. I am using socketio and socketio client my both the socket version are same 4.5.1 but it's not even connecting. I have tried to use old version of socket but its also not working and I have also tried to change my localhost port to 4000 but it's also not working.
My server code:
const express = require('express');
var bodyParser = require('body-parser');
const app = express();
const http = require('http');
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server);
const port = process.env.PORT || 3000;
require('./src/config/database')
const user_routes = require('./src/user/users.routes');
app.use(bodyParser.urlencoded({extended: true}))
app.use(express.json())
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
app.use('/User', user_routes)
io.on('connection', (socket) => {
console.log('a user connected');
socket.on('send_message',(data)=>{
console.log("received message in server side",data)
io.emit('received_message',data)
})
socket.on('disconnect', () => {
console.log('user disconnected');
});
});
server.listen(port, () => {
console.log( `Server running at http://localhost:${port}/`);
});
My app socketservice file code:
import io from 'socket.io-client';
const SOCKET_URL = 'http://localhost:3000'
class WSService {
initializeSocket = async () => {
try {
this.socket = io(SOCKET_URL, {
transports: ['websocket']
})
console.log("initializing socket", this.socket)
this.socket.on('connect', (data) => {
console.log("=== socket connected ====")
})
this.socket.on('disconnect', (data) => {
console.log("=== socket disconnected ====")
})
this.socket.on('error', (data) => {
console.log("socekt error", data)
})
} catch (error) {
console.log("scoket is not inialized", error)
}
}
emit(event, data = {}) {
this.socket.emit(event, data)
}
on(event, cb) {
this.socket.on(event, cb)
}
removeListener(listenerName) {
this.socket.removeListener(listenerName)
}
}
const socketServcies = new WSService()
export default socketServcies
Where I have marked it should be connected = true but it's false in the dev console I have done console log so check that it's connecting or not and I can see that it's not connecting. How to make it connect?
There is no error in my app or server I have checked many times and my server is also running when I am running my app.
Answering my own question
The problem was i was using android emulator and android in an emulator can't connect to localhost you need to use the proxy ip so when i add http://10.0.2.2:3000 in const SOCKET_URL = 'http://10.0.2.2:3000' than its working fine
credit goes to gorbypark who told me this in discord
I'm assuming that your front and back runs in localhost. The documentation says that if the front-end is in the same domain as the back-end, you don't need to use the URL. Since you have the options parameter declared, you can use the default argument window.location in first place:
class WSService {
initializeSocket = async () => {
try {
this.socket = io(window.location, {
transports: ['websocket']
})
console.log("initializing socket", this.socket)
this.socket.on('connect', (data) => {
console.log("=== socket connected ====")
})
this.socket.on('disconnect', (data) => {
console.log("=== socket disconnected ====")
})
this.socket.on('error', (data) => {
console.log("socekt error", data)
})
} catch (error) {
console.log("scoket is not inialized", error)
}
}
emit(event, data = {}) {
this.socket.emit(event, data)
}
on(event, cb) {
this.socket.on(event, cb)
}
removeListener(listenerName) {
this.socket.removeListener(listenerName)
}
}
Don't specify the host/port for socket-io to connect to. It can figure it out on its own.
Per documentation, it tries to connect to window.location if no URL is specified as an argument.
So instead of
this.socket = io(SOCKET_URL, {
transports: ['websocket']
})
Just do
this.socket = io()
I am not sure it works with other arguments. You could try like this
this.socket = io(undefined, {
transports: ['websocket']
})

supertest changing url at every test

I'm new to backend development and i face a problem that i don't understand.
I set up the 1st route of my API called "health" who just return a simple message to know if my server is up.
This route looks to works as expected.
However,
when I try to test this route with the method "toMatchSnapshot" from
jest API, the test is not passing because of the in the url is changing constantly.
My test file "index.test.ts":
const request = supertest.agent(app);
describe("app", () => {
it("should return a successful response for GET /health", async () => {
const res = await request.get("/health");
res.header = omit(res.header, ["date"]);
expect(res).toMatchSnapshot();
});
});
index of the server "index.ts":
const app = express();
expressService(app);
if (require.main === module) {
app.listen(PORT, () => {
console.log("server started at http://localhost:" + PORT);
});
}
export default app;
my function "expressService":
const expressService = (app: Application) => {
app.use(cors());
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(api);
};
export default expressService;
My PORT variable: PORT = 3000;
- "url": "http://127.0.0.1:49694/health",
+ "url": "http://127.0.0.1:52568/health",
this is where the test is failing.
Thank you for your answers.
The doc of supertest says:
You may pass an http.Server, or a Function to request() - if the server is not already listening for connections then it is bound to an ephemeral port for you so there is no need to keep track of ports.
You need to pass a Node.js http.Server object to supertest.agent(), then you can use the specific PORT for testing.
Here is the solution:
index.ts:
import express from 'express';
import expressService from './expressService';
import http from 'http';
const app = express();
const PORT = process.env.PORT || 3000;
expressService(app);
function createHttpServer() {
const httpServer: http.Server = app.listen(PORT, () => {
console.log('server started at http://localhost:' + PORT);
});
return httpServer;
}
if (require.main === module) {
createHttpServer();
}
export default createHttpServer;
expressService.ts:
import { Application } from 'express-serve-static-core';
import express, { Router } from 'express';
import cors from 'cors';
const expressService = (app: Application) => {
app.use(cors());
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
const api = Router();
api.get('/health', (req, res) => {
res.sendStatus(200);
});
app.use(api);
};
export default expressService;
index.spec.ts:
import createHttpServer from './';
import { agent } from 'supertest';
import { omit } from 'lodash';
const httpServer = createHttpServer();
const request = agent(httpServer);
afterAll(done => {
httpServer.close(done);
});
describe('app', () => {
it('should return a successful response for GET /health', async () => {
const res = await request.get('/health');
res.header = omit(res.header, ['date']);
expect(res).toMatchSnapshot();
});
});
Unit test result:
PASS src/stackoverflow/57409561/index.spec.ts (7.853s)
app
✓ should return a successful response for GET /health (61ms)
console.log src/stackoverflow/57409561/index.ts:12
server started at http://localhost:3000
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 1 passed, 1 total
Time: 8.66s
Snapshot:
// Jest Snapshot v1
exports[`app should return a successful response for GET /health 1`] = `
Object {
"header": Object {
"access-control-allow-origin": "*",
"connection": "close",
"content-length": "2",
"content-type": "text/plain; charset=utf-8",
"etag": "W/\\"2-nOO9QiTIwXgNtWtBJezz8kv3SLc\\"",
"x-powered-by": "Express",
},
"req": Object {
"data": undefined,
"headers": Object {
"user-agent": "node-superagent/3.8.3",
},
"method": "GET",
"url": "http://127.0.0.1:3000/health",
},
"status": 200,
"text": "OK",
}
`;
Here is the completed demo: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/57409561
Simple enough solution:
const request = require('supertest'); // npm i -ED supertest
const app = require('../app'); // your expressjs app
const { url } = request(app).get('/'); // next, just use url
console.debug(url); // prints: http://127.0.0.1:57516/

Web3 web3.eth.sendSignedTransaction Invalid params

Im very new to ethereum i have set up a private network using the pantheon client. i have successfully deployed a contract to the network and all interactions with the contract work when using through remix.
I am trying to set up a relay where a transaction is signed client side, sent to a nodeJs server and then the server proxies the transaction to the contract. however when i pass the signed transaction to sendSignedTransaction() i get the error Invalid params, to me this is very vague and i am unsure what i'm doing wrong / what the invalid params are. (any advice on how to debug this?)
UPDATE
using web3 v1.2.0
Error
Error: Returned error: Invalid params
at Object.ErrorResponse (/Users/ghost/node_modules/web3-core-helpers/src/errors.js:29:16)
at Object.<anonymous> (/Users/ghost/node_modules/web3-core-requestmanager/src/index.js:140:36)
at /Users/ghost/node_modules/web3-providers-ws/src/index.js:121:44
at Array.forEach (<anonymous>)
at W3CWebSocket.WebsocketProvider.connection.onmessage (/Users/ghost/node_modules/web3-providers-ws/src/index.js:98:36)
at W3CWebSocket._dispatchEvent [as dispatchEvent] (/Users/ghost/node_modules/yaeti/lib/EventTarget.js:107:17)
at W3CWebSocket.onMessage (/Users/ghost/node_modules/websocket/lib/W3CWebSocket.js:234:14)
at WebSocketConnection.<anonymous> (/Users/ghost/node_modules/websocket/lib/W3CWebSocket.js:205:19)
at WebSocketConnection.emit (events.js:188:13)
at WebSocketConnection.processFrame (/Users/ghost/node_modules/websocket/lib/WebSocketConnection.js:552:26)
at /Users/ghost/node_modules/websocket/lib/WebSocketConnection.js:321:40
at process.internalTickCallback (internal/process/next_tick.js:70:11)
Contract
pragma solidity ^0.5.1;
import "./Ownable.sol";
contract Entry is Ownable {
mapping (address => string) hash;
function addEntry(string memory _hash) public {
hash[msg.sender] = _hash;
}
function getHash() public view returns(string memory){
return hash[msg.sender];
}
}
Relay Server
const Web3 = require('web3');
const express = require('express')
const app = express()
const port = 3003
const bodyParser = require('body-parser');
const cors = require('cors')
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json())
app.use(cors())
var web3 = new Web3(Web3.givenProvider || "ws://localhost:7002");
app.post('/transaction/send', async (req, res) => {
const {tx, data} = req.body;
web3.eth.sendSignedTransaction(tx, function (err, transactionHash) {
if(err) console.log(err);
console.log(transactionHash);
});
})
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
Front end
import React from 'react';
import './App.css';
import Web3 from 'web3';
import request from 'request-promise';
const Tx = require('ethereumjs-tx').Transaction;
const web3 = new Web3("http://localhost:8545");
const privKey = '[My Priv key here]';
const contractADDRESS = "0x4261d524bc701da4ac49339e5f8b299977045ea5";
const addressFrom = '0x627306090abaB3A6e1400e9345bC60c78a8BEf57';
const contractABI = [{"constant":false,"inputs":[{"name":"_hash","type":"string"}],"name":"addEntry","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getHash","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}];
function App() {
async function sendTx(){
const data = await extraData();
web3.eth.getTransactionCount(addressFrom).then(txCount => {
const txData = {
nonce: web3.utils.toHex(txCount),
gasLimit: web3.utils.toHex(25000),
gasPrice: web3.utils.toHex(10e9),
to: contractADDRESS,
from: addressFrom,
data: data
}
sendSigned(txData, function(err, result) {
if (err) return console.log('error', err)
console.log('sent', result)
})
})
}
async function sendSigned(txData, cb) {
const privateKey = new Buffer(privKey, 'hex')
const transaction = new Tx(txData)
transaction.sign(privateKey)
const serializedTx = transaction.serialize().toString('hex')
const response = request({
method: 'POST',
uri: 'http://127.0.0.1:3003/transaction/send',
body: {
tx: serializedTx,
data: 'somehashhh'
},
json: true,
});
}
async function extraData() {
const contractInstance = new web3.eth.Contract(contractABI, contractADDRESS);
return await contractInstance.methods.addEntry('somehashhh').encodeABI();
}
return (
<div className="App">
<header className="App-header">
<div onClick={() => sendTx()}>Submit transaction</div>
</header>
</div>
);
}
export default App;
This is the txData sent from front end
{
data: "0x17ce42bd0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000a736f6d6568617368686800000000000000000000000000000000000000000000"
from: "0x627306090abaB3A6e1400e9345bC60c78a8BEf57"
gasLimit: "0x61a8"
gasPrice: "0x2540be400"
nonce: "0x0"
to: "0x4261d524bc701da4ac49339e5f8b299977045ea5"
}
After a lot of trail and error an 0 suggestions on stack overflow working, i have got the transaction signing working!. In the end i came away from using ethereumjs-tx (which for some reason is recommended by a lot of people) and used just pure Web3.
Front end client
async function sendTx(){
const { address: from } = web3.eth.accounts.privateKeyToAccount(PRIVATE_KEY)
const contract = new web3.eth.Contract(CONTRACT_ABI, CONTRACT_ADDRESS)
const query = await contract.methods.updateCount();
const signed = await web3.eth.accounts.signTransaction({
to: CONTRACT_ADDRESS,
from,
value: '0',
data: query.encodeABI(),
gasPrice: web3.utils.toWei('20', 'gwei'),
gas: Math.round((await query.estimateGas({ from })) * 1.5),
nonce: await web3.eth.getTransactionCount(from, 'pending')
}, PRIVATE_KEY)
const response = await request({
method: 'POST', json: true,
uri: 'http://127.0.0.1:3003/transaction/send',
body: {
tx: signed.rawTransaction,
data: 'some data'
}
});
console.log(response);
}
Relay Server
const Web3 = require('web3');
const express = require('express')
const app = express()
const port = 3003
const bodyParser = require('body-parser');
const cors = require('cors')
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json())
app.use(cors())
var web3 = new Web3(Web3.givenProvider || "ws://localhost:7002");
app.post('/transaction/send', async (req, res) => {
const {tx, data} = req.body;
web3.eth.sendSignedTransaction(tx)
.on('transactionHash', (txHash) => res.json({txHash}))
.on('error', console.log)
})
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
hopefully this can help someone else
👍

Categories