NUXT (SSR Mode) connect Lavarel Pusher Socket - javascript

I want to connect the Laravel Pucher Socket to NUTX.js ( SSR Mode) Application.
Above code add-in socket socketio.js plugins file. this code not working.
Anyone tell me what's wrong.
How to connect Socket in NUXT SSR mode.
import Echo from "laravel-echo";
import config from "../config/config.global";
export default async ({ store, $axios }) => {
const port = 6001;
window.io = require("socket.io-client");
window.Pusher = require("pusher-js");
console.log(typeof io, "socketIO");
if (typeof io !== "undefined") {
// connect to web socket
try {
window.Echo = new Echo({
broadcaster: "pusher",
key: config.secretKey,
wsHost: config.socketUrl,
wsPort: port,
disableStats: true,
auth: {
headers: config.header
}
});
console.log("connect to socket");
} catch (error) {
console.log(error.message);
}
}
function listenStock({ channelName, eventName }, callback) {
console.log("callback",callback);
window.Echo.channel(channelName).listen(eventName, callback);
}
// Get user Balance Socket
listenStock(
{
channelName: `BalanceUpdateEvent.${store.getters.GetUserUUID}`,
eventName: "BalanceUpdateEvent"
},
({ data }) => {
try {
console.log(data,"Data");
} catch (ex) {
console.log(ex);
}
}
);
};

In Nuxt have two Mode SPA and SSR.
SPA run only client side
SSR run Client and Server Side.
So i created repositories about laravel echo socket pusher service connect to NUXT Mode.
NUXT (SSR Mode):
https://github.com/mankarsandesh/nuxt-socket-laravel-echo-SSR
NUXT (SPA Mode)
https://github.com/mankarsandesh/nuxt-socket-laravel-echo-SPA

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.

Struggling to find memory leak. NodeJS, Express, MongoDB

so I have a NodeJS with Express configured for API calls to get data from my backend Database.
Everything works great except there is a memory leak that I can't seem to solve no matter what I do. I have narrowed it down to a MongoDB fetch call, that grabs data from MongoDB.
Since the Data being sent is the same, and to avoid multiple requests to MongoDB, I created a top level variable that fetches that data so on a request it sends that, vs doing a fetch constantly as it would be 1000's of requests every minute.
I have also set the --max_old_space_size variable to 4096 and higher at 8192 and will eventually crash also.
Below is the fetch code.
//router get apis.js
import { Model } from '../../dbmodels/models.js';
let data = null;
// Bot interval
setInterval(async () => {
try {
data = await tokenModel.find({
$or: [
{ "currentRanks.minuteTokenRank": {$lt: 51} },
{ "currentRanks.fiveMinuteTokenRank": {$lt: 51} },
{ "currentRanks.fifteenMinuteTokenRank": {$lt: 51} },
{ "currentRanks.thirtyMinuteTokenRank": {$lt: 51} },
{ "currentRanks.hourlyTokenRank": {$lt: 51} },
{ "currentRanks.dailyTokenRank": {$lt: 51} },
{ "currentRanks.weeklyTokenRank": {$lt: 51} }
]
}).lean();
} catch (error) {
console.error(error);
return;
}
}, 45000);
export async function main(req, res) {
let dataRes = data;
try {
res.status(200).json(dataRes);
dataRes = null;
} catch {(err) => {
res.status(500).json({ message: err.message })
console.log('err', err.message)
}
}
//console.log('Get Top Data')
}
//main server.js file
import dotenv from "dotenv"
dotenv.config()
import express from 'express';
const app = express();
import { createServer } from 'https';
import { createServer as _createServer } from 'http';
import { readFileSync } from 'fs';
import compression from "compression";
import pkg from 'mongoose';
const { connect, connection } = pkg;
import cors from 'cors';
import auth from './utils/auth.js'
connect(process.env.DB_URL);
let mongoClient = connection;
mongoClient.on('error', (error) => console.error(error));
mongoClient.once('open', () => console.log(`Cncted to DB ${mongoClient.name}`));
app.use(compression());
app.use(cors({ origin: ['http://localhost:3000']}));
// Apis route
import apis from './apis/apis.js';
app.use('/api', auth, apis);
//listen both http & https
const httpServer = _createServer(app);
const httpsServer = createServer({
key: readFileSync('redacted.pem'),
cert: readFileSync('redacted.pem'),
}, app);
httpServer.listen(3000, () => console.log('Server Started port 3000'));
httpsServer.listen(3001, () => {
console.log('HTTPS Server running port 3001')
})
So looks like I was able to find the leak. It wasn't with any of the API's I posted. But a hidden one that I use or Web3. There is a known bug on the web3 package leaving connections open.
This is tied to the data I am retrieving above which is why it seemed to me like it was this API, but further troubleshooting found the real issue.
Here is the issue in case anyone uses web3 packages and runs into similar.
https://github.com/web3/web3.js/issues/3042#issuecomment-663622882

ReactJS Browser Websocket Connection to SpringBoot Websocket

I'm trying to establish a websocket between a SpringBoot app at localhost:8090 and a React app at localhost:3000. Through Postman i'm able to establish a websocket connection and send/receive messages at localhost:8090/api/web-socket.
When I run the React app, the application loads but isn't able to establish the websocket connection to Springboot. I've tried the connection to both 127.0.0.1 and localhost with no luck. When I try to debug in the browser console I see the following error: "WebSocket connection to 'ws://localhost:8090/api/web-socket' failed:" notice there isn't any error details. The error location references line 28 of browser.js which is
else { native_instance = new NativeWebSocket(uri); }
Here is the full block:
function W3CWebSocket(uri, protocols) {
var native_instance;
if (protocols) {
native_instance = new NativeWebSocket(uri, protocols);
}
else {
native_instance = new NativeWebSocket(uri);
}
What is this error? How can I resolve it?
Here is the what the React code for establishing the socket connection:
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import {w3cwebsocket as W3CWebSocket} from "websocket";
import './index.css';
const client = new W3CWebSocket('ws://localhost:8090/api/web-socket');
export default class App extends Component{
onButtonClicked = (value) => {
client.send(JSON.stringify({
type: "message",
msg: value
}
));
}
componentDidMount() {
client.onopen = () => {
console.log('websocket client connected');
};
client.onmessage = (message) =>{
const dataFromServer = JSON.parse(message.data);
console.log("reply from socket server: ", dataFromServer);
}
}
render() {
return(
<div>
<button onClick={() => this.onButtonClicked("Example message from client to server")}>Send Message(start SAP)</button>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('root'));
UPDATE - RESOLVED
So after some further digging i discovered the issue was related to cross origin setting on the SpringBoot side. For anyone that runs into this issue in the future try the to add the following to your Socket configuration class:
.setAllowedOrigins("*")
In full it would look something like this:
registry.addHandler(new SocketTextHandler(), "/your-route").setAllowedOrigins("*");

Vue.js + Nuxt.js: Can't connect with socket server using socket.io-client

I am using for client and server sides: socket.io-client v3.0.5
index.vue
import socket from '~/plugins/socket.js'
<script>
mounted() {
socket.open()
}
</script>
plugins/socket.js
import io from 'socket.io-client'
const options = {
path: '/socket.io',
transports: ['websocket'],
forceNew: true,
reconnectionAttempts: 3,
timeout: 2000,
reconnection: false,
}
const socket = io(process.env.PROXY_SOCKET_URL, options)
export default socket
nuxt.config.js
plugins: [
'~/plugins/socket.js',
],
And on mount i got this: 2 commas after '40' code in data of ws
My client side and server side not connecting because of 2 commas in data. I tested my socket server via SocketIo Client tool and it works.
My frontend and backend in docker.
How can i remove those commas?
You can use "nuxt-socket-io"(v1.1.18) module instead of socket.io-client. It helped me connect front and server.
Here my realization:
nuxt.config.js
modules: [
'nuxt-socket-io',
],
io: {
// module options
sockets: [
{
name: 'main',
default: true,
url: process.env.PROXY_SOCKET_URL,
},
],
},
index.vue
<script>
mounted() {
window.socket = this.$nuxtSocket({
path: '/socket.io',
transport: ['websocket'],
})
window.socket.open()
}
</script>
I've been playing with this the past few days, and have a module-free solution.
In order to run the socket.io server on the same server that nuxt is providing we need to get access to Nuxt's server. Luckily, Nuxt's listen hook provides the server once it has been started. We can use this server to start our socket.io server by adding the following to nuxt.config.ts:
import startSocketServer from "./server/sockets"
defineNuxtConfig({
...
hooks: { listen: (server) => startSocketServer(server) },
...
})
and inside of ~/server/sockets/index.ts we export a function that accepts this server and spins up the socket.io server:
import { Server as NuxtServer } from 'node:http'
import { Socket, Server } from "socket.io";
export default (nuxtServer: NuxtServer) => {
const io = new Server(nuxtServer)
io.on("connection", (socket: Socket) => {
socket.emit('message', "Hello World")
});
};
That's it for the server!
If we now have an app.vue that looks like this:
<script setup lang="ts">
import { io } from "socket.io-client";
const socket = io();
onMounted(() => socket.connect());
onUnmounted(() => socket.close());
const message = ref("");
socket.on("message", (data: string) => (message.value = data));
</script>
<template>
<div>{{ message }}</div>
</template>
We should see "Hello world" from the server when we load the page.

Angular Node | SocketIO | Event not emitted from node

I had asked this question before but here's a simple code for the same.
Im sending the data to Node from angular via websocket but I don't get the emitted event:
I've followed 10+ tutorials and forums, newest from here: https://www.youtube.com/watch?v=66T2A2dvplY&t=317s
service:
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs';
import { io } from 'socket.io-client';
#Injectable({
providedIn: 'root'
})
export class SocketService {
socket = io('ws://localhost:3000'); // adding 'http://localhost:3000' also doesnt work
constructor() {}
listen(eventName: string) {
return new Observable( subscriber => {
this.socket.on(eventName, data => {
subscriber.next(data);
});
});
}
emit(eventName: string, data) {
this.socket.emit(eventName, data);
}
}
from component's ngOnInit(), this is called:
this._socketService.listen('test event').subscribe( data => {
console.log("data from server: ", data);
});
server code of Node:
const app = require('./app');
const port = process.env.PORT || 3000;
const server = require('http').createServer(app);
const socketio = require('socket.io');
const io = socketio(server,
{
serveClient: true,
pingInterval: 60000,
pingTimeout: 60000000,
cors: {
origin: "http://localhost:4200",
methods: ["GET", "POST"],
credentials: true
}
});
io.on('connection', function (socket) {
console.log("A user connected ", socket.connected); // works till here for every ping interval
socket.emit('test event', 'here is some data'); // this is either not executed or doesn't work
});
server.listen(port);
socket.connected is always true in NODE server, but false in Angular
What Ive tried:
CORS has been suppressed, I hope that's not the issue cuz nothing is seen like so
changing io.('connection' ...) to io.connect('connect'...)
init this.socket = io(...) in constructor
There is no data exchange seen in Network or Network > WS tab in case I emit from Angular too
This is my 3rd day with this problem, I'll highly appreciate any help.
Thank you
your mixing protocols from client.
change
socket = io('ws://localhost:3000');
to
socket = io('http://localhost:3000', { withCredentials: true });
As mentioned in introduction under chapter What Socket.IO is not that socket.io is not a pure WS lib.

Categories