I am trying to send some data (number) from client to server via socket.emit. The problem is that server doesn't seem to receive any data because only null is consoled out or I am trying to get it wrong. Where might be a problem?
client side
useEffect(() => {
getMessages();
socket.emit("openedConversation", { conversationId });
}, []);
server side
io.on("openedConversation", ({ conversationId }) => {
console.log(conversationId);
});
};
check this code
io.on("openedConversation", conversationId => {
console.log(conversationId);
});
Related
I just started using Twilio services and there have been a few challenges. The phone number I send from the front end, I'm not able to make out if its actually being sent to the backend route. Whenever the GET request is done, it throws an error
": Required parameter "opts['to']" missing. twilio".
The first error is what I am getting now.
My form sends this to the backend:
case 2:
const Phoneno = {
phone:countryCode+PhoneNumber
};
axios.post('http://localhost:4000/app/otp', { data :Phoneno });
console.log(Phoneno)
my route for sending otp:
router.post('/otp', async(req, res)=>{
client.verify.v2.services("VERIFY_SERVICE_SID")
.verifications
.create({to:req.body.phone, channel: 'sms'})
.then((verification) => {
console.log(verification.status);
return callback(null);
}).catch((e) => {
console.log(e);
return callback(e);
});
});
In that console.log, I get this,
"{phone: '+91**********'}
phone: "+91**********"(my actual number)
[[Prototype]]: Object"
Also, when I hardcode the phone number, the route works perfectly fine. And when i send an HTTP request to the route, then also it sends an otp to my phone number. But is not able to recognize the data sent from the frontend.
My http request:
POST http://localhost:4000/app/otp
Content-Type: application/json
{
"Phoneno":"+9199********"
}
Please help me out. Thanks a lot for looking into it.
You are making a GET request to your back-end, but you are trying to get the data from the request body. GET requests do not have a body.
You're also trying to send the data by passing it in an object as the second argument to axios.get, but that argument should be a config object. To send the data in the query for the GET request it should be under the params key for that object:
const Phoneno = {
phone:countryCode+PhoneNumber
};
axios.get('http://localhost:4000/app/otp', { params: Phoneno });
Then on the back-end, read the data from the query, using req.query.phone:
router.get('/otp', async(req, res)=>{
client.verify.v2.services(VERIFY_SERVICE_SID)
.verifications
.create({to:req.query.phone, channel: 'sms'})
.then((verification) => {
console.log(verification.status);
return callback(null);
}).catch((e) => {
console.log(e);
return callback(e);
});
However, this might not be a good idea because an attacker can easily create a URL to your site and add the phone number in the query parameters and use it to perform SMS pumping.
I'd actually recommend you change your back-end to a POST request and send the data from the front end in a POST request with the data in the body of the request:
const Phoneno = {
phone:countryCode+PhoneNumber
};
axios.post('http://localhost:4000/app/otp', { data: Phoneno });
router.post('/otp', async(req, res)=>{
client.verify.v2.services(VERIFY_SERVICE_SID)
.verifications
.create({to:req.body.data.phone, channel: 'sms'})
.then((verification) => {
console.log(verification.status);
return callback(null);
}).catch((e) => {
console.log(e);
return callback(e);
});
i am trying to build an app and i am very new to all this. So I've built a very simple function to get data from firestore and it works fine from a moment. This is the code:
async getData(req, res) {
const dataRef = db.collection(`${req.body.banco}`)
let result = []
dataRef.onSnapshot(docSnapshot => {
docSnapshot.forEach(doc => {
const data = doc.data()
result.push(data)
})
console.log(result)
return res.status(200).send(result)
}, (error) => {
console.log(`Erro encontrado: ${error}`)
})
}
My problem is that when I try to update any field from the document. It gets updated but I end up receiving this error:
node:_http_outgoing:576
throw new ERR_HTTP_HEADERS_SENT('set');
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at new NodeError (node:internal/errors:372:5)
at ServerResponse.setHeader (node:_http_outgoing:576:11)
at ServerResponse.header (C:\Users\paulo\Desktop\sirius-back\functions\node_modules\express\lib\response.js:794:10)
at ServerResponse.send (C:\Users\paulo\Desktop\sirius-back\functions\node_modules\express\lib\response.js:174:12)
at ServerResponse.json (C:\Users\paulo\Desktop\sirius-back\functions\node_modules\express\lib\response.js:278:15)
at ServerResponse.send (C:\Users\paulo\Desktop\sirius-back\functions\node_modules\express\lib\response.js:162:21)
at C:\Users\paulo\Desktop\sirius-back\functions\src\controller\createDocs.js:70:40
at QueryWatch.onNext (C:\Users\paulo\Desktop\sirius-back\functions\node_modules\#google-cloud\firestore\build\src\reference.js:1914:13)
at QueryWatch.pushSnapshot (C:\Users\paulo\Desktop\sirius-back\functions\node_modules\#google-cloud\firestore\build\src\watch.js:469:18)
at QueryWatch.onData (C:\Users\paulo\Desktop\sirius-back\functions\node_modules\#google-cloud\firestore\build\src\watch.js:353:26) {
code: 'ERR_HTTP_HEADERS_SENT'
}
the app crashes and i have to start it over.
What is the reason of this? How can i get realtime updates from firestore databse after I update something from?
In Express you handle each requests by sending a single response to it. Since res a a response object, you can only send a response to the caller once. But since you're using onSnapshot, your code gets called for every change to the data too.
So initially, you load the data and send a response to the caller and all is 👍
But then when an update is made to the database, your code executes again and tries to send another response to the caller - and this is when you get an error.
The solution is to read the data only one with something like:
async getData(req, res) {
const dataRef = db.collection(`${req.body.banco}`)
let result = []
dataRef.get().then((docSnapshot) => {
docSnapshot.forEach((doc) => {
const data = doc.data()
result.push(data)
})
console.log(result)
return res.status(200).send(result)
}, (error) => {
console.log(`Erro encontrado: ${error}`)
})
}
Or a bit simplified:
async getData(req, res) {
const dataRef = db.collection(`${req.body.banco}`)
dataRef.get().then((docSnapshot) => {
const result = docSnapshot.docs.map((doc) => doc.data());
return res.status(200).send(result)
}, (error) => {
console.log(`Erro encontrado: ${error}`)
})
}
Once you've called res.send(...) the request is complete and the client stops listening. Sending further updates to a response is not possible with an Express request/response model like you're using.
Also see:
How to send multiple responses while computing in Express.js?
Sending multiple responses(res.json) with the same response object in Express.js
and more from searching for how to send multiple responses for a single request in express
You'll need to choose an infrastructure that allows a client to keep listening. Heads up: building something like that is quite involved, and you're likely better off if you use the client-side Firestore SDK to implement such realtime listeners
When emit a event to the websocket server, the server receive the event once and send a response, but the client receive the event multiple time:
result expected
result received
client side:
client.emit("test", {
room: props.room,
});
client.on("testResponse", () => {
console.log("test response app");
});
server side :
socket.on("test", (data: { room: string }) => {
console.log("test");
io.in(data.room).emit("testResponse", {});
});
UPDATE:
on the client side I got to put the socket.on('response,()=>{...}) in the UseEffect of the component and add a socket.off in the return of the useEffect
useEffect(() => {
socket.on("testResponse", () => {
console.log("test response app");
});
return () => {
socket.off("testResponse");
};
});
I have this code in my service worker:
messaging.onBackgroundMessage(function (payload) {
console.log("onBackgroundMessage email and contact_link:");
console.log(payload.data.email,payload.data.contact_link);
self.clients.matchAll().then(clients => {
clients.forEach(client => client.postMessage({
msg: "This is a message from the SW",
email: payload.data.email,
contact_link: payload.data.contact_link
}));
})
});
I have this code on the client:
navigator.serviceWorker.addEventListener('message', payload => {
console.log("Message from ServiceWorker");
console.log(payload.data.msg, payload.data.email, payload.data.contact_link);
});
I get the data properly on the console from the service worker, however the client's console says all the data is undefined.
Why is that, what am I doing wrong?
I still do not know why it does not work, but I used this code on the server:
const channel = new BroadcastChannel('sw-messages');
channel.postMessage(payload.data);
And this code on the client instead:
const channel = new BroadcastChannel('sw-messages');
channel.addEventListener('message', event => {
console.log('Received:', event.data);
});
It works well.
I am using nodejs grpc server streaming to deliver realtime data from server to the clients. As the clients want to listen to the data, they should call a server function which returns a server stream. Then if the client want to end the listening I guess it should call the end method on the call object. But unfortunately I couldn't find any clue on the documentation about how to do this. I have tried call.end and call.destroy and call.cancel but end and destroy did nothing and cancel throws the following error. The sample client side code is as following:
function getData(token, userId) {
const data = {
token,
userId
}
let call = DataService.getData(data)
call.on('data', res => {
console.log(res)
})
call.on('status', console.log);
call.on('error', console.log);
setTimeout(() => {
console.log('destroy')
call.cancel()
}, 5000)
}
and the error is:
Error: 1 CANCELLED: Cancelled on client
at Object.callErrorFromStatus (...grpc\node_modules\#grpc\grpc-js\build\src\call.js:31:26)
at Object.onReceiveStatus (...grpc\node_modules\#grpc\grpc-js\build\src\client.js:330:49)
at Object.onReceiveStatus (...grpc\node_modules\#grpc\grpc-js\build\src\client-interceptors.js:299:181)
at ...grpc\node_modules\#grpc\grpc-js\build\src\call-stream.js:145:78
at processTicksAndRejections (internal/process/task_queues.js:75:11) {
code: 1,
details: 'Cancelled on client',
metadata: Metadata { internalRepr: Map(0) {}, options: {} }
}