I request via mqtt protcol but my own browser request wss format - reactjs

I want to make mqtt request to interact with my own broker . It should be done (client) using react or next.js and mqtt.js package.
I was attempt, but when I inspect a browser , It seems my browser attempt to ws connection and it currupt:
I was install this package :
npm i mqtt --save
Below are all stuffs which I attempt using these:
import React, { useEffect, useState } from "react";
import mqtt from "mqtt";
function Send() {
const [status, setStatus] = useState("Not Connect");
useEffect(() => {
//const client = mqtt.connect("wss://test.mosquitto.org:8081/mqtt");
const client = mqtt.connect("mqtt://171.22.25.40:1883");
client.on("connect", () => {
setStatus("Connect");
client.subscribe("IHS", (err) => {
if (!err) {
client.publish("IHS", "Test Message");
}
});
});
}, []);
return (
<div>
<p>{`Status: ${status}`}</p>
</div>
);
}
export default Send;
Is I missed an specific configuration for mqtt function ? How can I fix it?
Edit:
I append a configuration to mqtt variable like these snipped:
const options = {
port: 1883,
host: "171.22.25.40",
protocol: "mqtt",
keepalive: 10,
protocolId: "MQTT",
reconnectPeriod: 2000,
};
const client = mqtt.connect("mqtt://171.22.25.40:1883", options);
But nothing happened.
Edited:
I use this config in the mosquito config file, from C# can connect to mqtt but can't connect to wss
port 1883
listener 9001
protocol websockets
allow_anonymous true

You can not use native MQTT protocol from within the browser, because the browsers JavaScript sandbox will not allow you to make arbitrary TCP connections. You can only make HTTP or WS connections.
The MQTT.js package will always convert any mqtt:// URL to a ws:// when run in the browser.
You will need to make sure your broker is configured to accept MQTT over WebScoket connections and set the port number in the URL to match.

Related

localhost:3000 This site can’t be reached after installing http-proxy-middleware

I am building a newsletter sign-up form that uses .netlify-lambda to send my form submission to Mailchimp. I installed http-proxy-middleware to help the front end find the netlify-lambda folder. After writing the proxy setup code below my React start script stopped working. It appears the proxy setup below is interfering with localhost:3000.
My proxy setup looks like this
const proxy = require('http-proxy-middleware');
module.exports = function(app) {
console.log('Using proxy...')
app.use(proxy('/.netlify/functions/', {
target: 'http://localhost:9000/',
"pathRewrite": {
"^\\.netlify/functions": ""
}
}));
};
If the target is localhost:9000 why is it interfering with localhost:3000?
When I start my Lambda server it says: Lambda server is listening on 9000.
I am also getting this error when trying to compile my client app.
crbug/1173575, non-JS module files deprecated
Short answer (for #lachnroll and anyone who might be encountering the same problem):
Please use const { createProxyMiddleware } = require("http-proxy-middleware") and app.use(createProxyMiddleware('/.netlify/functions/' ...)...) , instead of using const proxy = require('http-proxy-middleware'); and app.use(proxy("/.netlify/functions/" ...)...) , it should work.
Long one:
I've come across the same "can't be reached" thing in a React project when using http-proxy-middleware(2.0.3), until I changed const proxy = require('http-proxy-middleware'); and proxy("/.netlify/functions/" ...) to const { createProxyMiddleware } = require("http-proxy-middleware"); and app.use(createProxyMiddleware('/.netlify/functions/' ...)...) , I think the proxy has been removed, see: https://github.com/chimurai/http-proxy-middleware#readme

How to access backend after deploying website on Heroku?

My backend runs on port 5000 on localhost. So obviously when I connect to the backend from the frontend using const socket = io.connect('http://localhost:5000') others around the world will not be able to access it. I've deployed the React App on Heroku.
[https://murmuring-reaches-27066.herokuapp.com/]
Copy ID button isn't working because I don't understand how to connect to the backend when it's on production mode.
My Backend code (Only included relevant code)
const express = require("express")
const http = require("http")
const app = express()
const server = http.createServer(app)
const io = require("socket.io")(server, {
cors: {
origin: "https://murmuring-reaches-27066.herokuapp.com/",
methods: [ "GET", "POST" ]
}
})
Any help is appreciated.

Can't establish connection between React JS & Django Channels

I have a web app using Django Rest Framework and React. I am trying to add web sockets to it. I opted for Django channels as they are the most recommended.
However, I keep getting this error Firefox can’t establish a connection to the server at ws://localhost:3000/ws/canvas_data & then the socket is closed automatically.
Apparently, the connexion can not be maintained between the frontend & the backend. I tried several options in the Routing URLs but nothing worked.
Maybe the problem is in the port since the same is used by HTTP & ws.
This is my first time dealing with Django Channels so please excuse my lack of knowledge.
This is the consumer:
from channels.generic.websocket import WebsocketConsumer, AsyncWebsocketConsumer
from time import sleep
import json
class WSConsumer(AsyncWebsocketConsumer):
async def connect(self):
print("CONNECTION IS NOW OPEN !!")
await self.accept()
for i in range(20): #The logic should be here, this is just an example to test
await self.send(json.dumps({"nom_rapport": "pv"}))
sleep(1)
async def disconnect(self, message):
print("CONNECTION IS NOW CLOSED !!")
pass
the asgi.py configuration:
import os
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
from django.urls import path
from Dashboard.consumers import WSConsumer
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Dashboard_sise.settings')
application = ProtocolTypeRouter({
'http': get_asgi_application(),
'websocket': URLRouter([
path(r'ws/canvas_data/', WSConsumer.as_asgi()),
])
})
settings.py file:
INSTALLED_APPS = [
.....
'channels',
'rest_framework',
.....
]
WSGI_APPLICATION = 'Dashboard_sise.wsgi.application'
ASGI_APPLICATION = 'Dashboard_sise.asgi.application'
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": ['redis://localhost:6379']
}
},
}
The WebSocket is declared like this:
componentDidMount(){
var socketPath = 'ws://localhost:3000/ws/canvas_data';
const Socket = new WebSocket(socketPath);
Socket.onopen = () => {
console.log('Socket is connected');
}
Socket.onmessage = (e) => { //Logic will be placed here
console.log("MESSAGE :", e.data);
this.setState({messages: e.data});
};
Socket.onclose = (e) => {
console.error('Chat socket closed unexpectedly');
};
}
The front end is running on port 3000, while the back is on port 8000.
Thank you in advance.
You have to start a server that supports sockets like daphne
daphne -b 0.0.0.0 -p 8001 django_project.asgi:application

Socket.io client is getting disconnected just after connection in NestJS

I'm trying to create chat with nestjs, and it is problem with its #SubscribeMessage(),
implementation with connection is working, but when I try to listen the emits from frontend and console the data in nestjs, it not works
import { Server, Socket } from 'socket.io';
import { Injectable } from '#nestjs/common';
import { InjectRepository } from '#nestjs/typeorm';
import { User } from '../entities/user.entity';
import { Repository } from 'typeorm';
import { Messenger } from './entities/messenger.entity';
#Injectable()
#WebSocketGateway(5000)
export class MessengerGateway implements OnGatewayConnection, OnGatewayDisconnect, OnGatewayInit {
constructor(
#InjectRepository(User)
private userRepository: Repository<User>,
#InjectRepository(Messenger)
private messageRepository: Repository<Messenger>,
) {}
#SubscribeMessage('loadPeople')
handleEvent(client: Socket, data){
console.log(data);
// this is not working
}
async afterInit(server: Server) {
console.log('Init');
}
#SubscribeMessage('is-online')
async handleConnection(client: Socket) {
console.log('connected');
// I can see this message in console
}
#SubscribeMessage('is-offline')
async handleDisconnect(client: Socket) {
console.log('disconnected');
// I can see this message in console
}
}
from front end I'm sending this requests
import { io } from "socket.io-client";
const ENDPOINT = "localhost:5000";
let socket
function App(){
useEffect(()=>{
socket = io(ENDPOINT)
socket.emit('loadPeople', {token: localStorage.token})
},[])
return (
//...
)
}
It works when I'm using the nodejs(expressjs) with socket.io,
But when I try to do this with nestjs, it's not working
Based on NestJS Websocket documentation, the NestJS socketIO server is still in v2.
#nestjs/platform-socket.io currently depends on socket.io v2.3 and socket.io v3.0 client and server are not backward compatible. However, you can still implement a custom adapter to use socket.io v3.0. Please refer to this issue for further information.
If you check the version compatibility, you will see that socketIO server v2 is not compatible with socketIO client v4.
The easiest solution would be to use socket.io-client v2.3.0 in your package.json of frontend.
Or, if you like to explore: socketIO server v3 is compatible with socketIO client v4. So I believe you can take a look into this issue (as mentioned in NestJS docs) and try to convert your NestJS socketIO server to support socketIO client v3. Hopefully, that would also support socketIO client v4 as well. (I didn't test this though!)
Hope this helps you. Cheers 🍻 !!!

Webpack dev server sockjs-node returns 404 error

I am running a simple Vue app with webpack that I created with the vue-cli. When I run the dev server wtih npm run serve, it shows several errors in the client console when using sockjs-node. I believe this module is used by webpack for hot reloading (HMR).
The first error is:
Access to XMLHttpRequest at 'http://192.168.1.4:8080/sockjs-node/info?t=1615330207390' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I can solve this in two ways by editing the devServer in my vue.config.js. The first method is by setting public: 'localhost:8080'; and the second is by setting headers: {'Access-Control-Allow-Origin': 'http://192.168.1.4:8080', 'Access-Control-Allow-Credentials': 'true'}.
In both cases, I then see the following two errors:
POST http://localhost:8080/sockjs-node/690/qvgqwbdo/xhr_streaming?t=1615330686134 404 (Not Found)
GET http://localhost:8080/sockjs-node/690/zympwfsc/eventsource 404 (Not Found)
How do I resolve these errors so that the hot reloader will connect?
In the function I set to devServer.before in my vue.config.js file, I created my own websockets using Socket.io on the same port as my devSever. When the function returned, the devServer could not use that port for websockets, so it failed to launch sockjs-node. Therefore, when the frontend client tried to connect to the devServer, the requests were going to my sockets, instead of the devServer sockets, and it was ignoring them. Hence the 404 errors.
Here is my original code:
// server.js
const { createServer } = require('http')
const io = require('socket.io')
const addSocketEvents = require('./socket-api')
const port = process.env.PORT || 8080
module.exports = {
port,
configure(app) {
// `app` is an instance of express
// add the websockets
const httpServer = createServer(app)
socket = io(httpServer, {
path: '/socket-api'
})
addSocketEvents(socket)
// starts the server
// cannot use app.listen() because that will not start the websockets
httpServer.listen(port)
}
}
// vue.config.js
const { port, configure } = require('./server')
module.exports = {
devServer: {
before: configure,
public: `localhost:${port}`,
},
}
To fix this issue, I needed to allow the devServer to use the original port for sockjs-node, and launch my sockets on a different port. However, because I need to use the same port in production (due to restrictions by my current hosting provider), I only want my sockets to use a different port when running the devServer. To do this, I simply created a different httpServer and launched it on a different port, then created a proxy in the devServer config for that port. In my configure function, I just check to see if it is running in dev or prod, and act accordingly.
My production server is a simple express instance which calls the same configure function after it is created. This allows me to put all my startup code in one place.
Here is my new code:
// server.js
const { createServer } = require('http')
const io = require('socket.io')
const addSocketEvents = require('./socket-api')
const port = process.env.PORT || 8080
const proxyPort = 8081
module.exports = {
port,
proxyPort,
configure(app) {
// `app` is an instance of express
// add the websockets
let httpServer, socketPort
if (process.env.NODE_ENV === 'development') {
httpServer = createServer()
socketPort = proxyPort
} else {
httpServer = createServer(app)
socketPort = port
}
// adds the socket-api to be used via websockets
socket = io(httpServer, {
path: '/socket-api'
})
addSocketEvents(socket)
// starts the server
httpServer.listen(socketPort)
}
}
// vue.config.js
const { port, configure } = require('./server')
module.exports = {
devServer: {
before: configure,
public: `localhost:${port}`,
proxy: {
'/socket-api': {
target: `http://localhost:${proxyPort}`,
ws: true
}
}
},
}

Resources