I'm simply trying to use sails.socket.emit() to send a message and I get this:
error: Sending 500 ("Server Error") response:
Error (SAILS:HOOK:SOCKETS:USAGE):: `sails.sockets.get()` cannot lookup socket w/o an id (got: `undefined`)
The code in the controller:
sayHiToFriend: function(req, res) {
var friendId = req.param('id');
sails.sockets.emit(friendId, 'privateMessage', {from: req.session.userId, msg: 'Hi!'});
res.json({
message: 'Message sent!'
});
}
And client side:
io.socket.get('/user/sayHiToFriend', function serverSays(err,users){
console.log('with headers: ', JWR.headers);
console.log('and with status code: ', JWR.statusCode);*/
if (err)
console.log(err)
console.log(JSON.stringify(users));
});
Do I have to pass the id as data to io.socket.get ? If so how?
edit: solution:
sails.sockets.emit(sails.sockets.id(req.socket), 'welcome', {custom: 'data here'});
I had the same problem. It seems like Sails.js has some internal problems or something else we cannot control...in my case few hours ago all worked fine and now it gives that error. I solved it simply compacting the array of the IDs with lodash:
User.findOne({'id': req.body.id}, function(error, user) {
var subscribers = _.compact(User.subscribers(user));
sails.sockets.emit(subscribers, "notification", {msg: req.body.msg});
});
and now everything works fine! Hope it helps!
Related
I have a rest API and an app that uses it. The app and postman can both make get requests perfectly. The problem is that on delete requests the app does not work Most of the time but postman works every time. The app also always receives an OK if it works or not. Any help would be appreciated. I am using Node.js and MongoDB for the api and Xamarin for the app
Delete code on server:
// Delete a fish with the specified fishId in the request
exports.delete = (req, res) => {
console.log("Atempting to delete fish with id: " + req.params.fishId)
Fish.findByIdAndRemove(req.params.fishId)
.then(fish => {
if (!fish) {
return res.status(404).send({
message: "Fish not found with id " + req.params.fishId
});
}
if (!Fish.findByID(req.params.fishId)) {
return res.status(200).send({
message: "Fish deleted sucsessfully"
});
}
return res.status(500).send({
message: "Could not delete fish with id " + req.params.fishId
});
}).catch(err => {
if (err.kind === 'ObjectId' || err.name === 'NotFound') {
return res.status(404).send({
message: "Fish not found with id " + req.params.fishId
});
}
return res.status(500).send({
message: "Could not delete fish with id " + req.params.fishId
});
});
};
Just wondering why is this with no callback/.then?
if (!Fish.findByID(req.params.fishId)) {
return res.status(200).send({
message: "Fish deleted sucsessfully"
});
}
Isn't findByID async just like findOneAndRemove?
findByID is async yes, you should handle it that way, or maybe a solution could be to check with ObjectID.isValid() before? Then check for the resolved document would be just enough.
I am building an Angular 4 and Node application. Once any user registers on the front-end, I am storing their data in the database, and then would like to send them a successful registration email using the nodemailer package.
Here's the Node js code:
router.post('/', function(req, res, next) {
SOME_DATABASE_FUNC() {
if(FAILED_CASE) {
return res.status(500).json({
title: 'An error occurred',
status: 500,
error: error
});
var mailOptions {...}
transporter.sendMail(mailOptions, function (error, info) {
if (error) {
console.log(error);
return res.status(500).json({
title: 'An error occurred',
status: 500,
error: error
});
}
console.log('Message', info.messageId, info.response);
return res.status(200).json({
message: 'Emailed successfully',
details: info
});
});
}
}
});
This code works perfectly, but it takes few seconds to send the email, and the user has to wait to show the success response which doesn't seem to fit good. Instead I would like to send it in the background may be as an asynchronous function or like a cron job.
But I am not sure how to transform the code to send it as a job instead of sending and waiting after the database transaction. Please help me out with the issue.
send response outside block of transporter.sendMail. So it will not wait for process of email send to be completed.
transporter.sendMail(mailOptions, function (error, info) {
if (error) {
console.log(error);
return res.status(500).json({
title: 'An error occurred',
status: 500,
error: error
});
}
console.log('Message', info.messageId, info.response);
});
return res.status(200).json({
message: 'Emailed successfully',
details: info
});
use Process.nextTick() for sending email
We knew that nodejs request and response is stream and you can do stuff after sending response stream in this way response time will decrease and other stuff will continue asynchronously after sending response to client.
You can send response successfully to client and then you can call send mail function.
I wrote this web Api and wrote first route on root i.e on localhost:3000/ or just / that will return a document from mongodb (I dont know If we can do this that get on "/") like this:
app.get('/data', function(req, res) {
quizz.findOne({ id: 1}, function (err, data) {
if (err) {
console.log(err)
} else {
console.log(data);
res.json(data);
}
})})
and I'm requesting from client like this:
this.http.get('https://localhost:3000/data').map(function (res) {
let body = res.json();
return body.body || {};
}).subscribe((data) => {
console.log(data);
})
but I'm getting this when I'm clicking on button(that actually has method inside which there is request method) Im getting this:
Also tried postman getting this error:
This seems to be like an error connecting to http://localhost:3000/. The response status was 0.
i use chef-api for express js and i wanna get only the ip address of node " server 1 " from a chef-server
im sending a request like this
Code :
chef.partialSearch("node", "name:server1",{"ip":"ipaddress"} ,function(err, res){
if (err){console.log(error);}
else{console.log(res);}
});
Or
chef.partialSearch("node", { q: "name:server1"} ,{"ip":"ipaddress"} ,function(err, res){
....
});
=> Response :
received status code 400 invalid value 'ipaddress' for no_key
function in code source :
partialSearch: function(index, qs, data, fn){
http_methods.post([config.host_url, "search", index].join("/"), qs, data, function(err, response){
return fn(err, response);
});
}
and i cant understand the correct syntax for the request (http) from the official website doc api_chef_server
Can you please give a valid syntax with example .
Thanks
What you probably want is something like this:
chef.getNode('server1', function(err, node) {
if(err) throw err;
console.log(node.automatic.ipaddress);
});
Finaly i found the correct syntax for both request
Simple Search :
chef.search("node", {q: "name:server1" }, function(err, res){
if (err){console.log(error);}
else{console.log(res);}
});
Partial Search :
chef.partialSearch("node", "chef_environment:prod", { name: ['name'] , 'ipaddress': ['ipaddress'] }, function(err, res){
if (err){console.log(error);}
else{console.log(res);}
});
Hope this can help someone else who is still looking .
I'm not really sure why I'm getting this error. It's a simple API built on express.js to be able to add and remove posts. The error occurs when I trigger the delete router. I've read that the error typically happens when there are two callbacks, however, I don't seem to be able find any double callbacks.
_http_outgoing.js:344
throw new Error('Can\'t set headers after they are sent.');
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:344:11)
at ServerResponse.header (/Users/bounty/Projects/_learning/react-express/node_modules/express/lib/response.js:718:10)
at ServerResponse.send (/Users/bounty/Projects/_learning/react-express/node_modules/express/lib/response.js:163:12)
at ServerResponse.json (/Users/bounty/Projects/_learning/react-express/node_modules/express/lib/response.js:249:15)
at /Users/bounty/Projects/_learning/react-express/server/routes/posts.js:86:9
at nextTickCallbackWith0Args (node.js:452:9)
at process._tickCallback (node.js:381:13)
Here is my posts.js router:
module.exports = function(router) {
var Post = require('../models/post.js');
// middleware for the api requests
router.use(function(req, res, next) {
// do logging
console.log('something is happening.');
next(); // make sure we go to our next route and don't stop here
});
// test route to make sure everything is working (accessed at GET http://localhost:8080/api)
router.get('/', function(req, res) {
res.json({ message: 'hooray! welcome to our api!' });
});
// all routes here
// routes that end in /posts
router.route('/posts')
// create a Post (accessed at POST http://localhost:7777/api/posts)
.post(function(req, res) {
var post = new Post();
post.postTitle = req.body.postTitle; // set the post name (comes from request)
// save post and check for errors
post.save(function(err) {
if (err)
res.send();
res.json({ message: 'post created!' });
});
})
// get all Posts (accessed at GET http://localhost:7777/api/posts)
.get(function(req, res) {
Post.find(function(err, posts) {
if (err)
res.send();
res.json(posts);
});
});
// routes that end in /posts for specific id
router.route('/posts/:post_id')
// get the post with that id
.get(function(req, res) {
Post.findById(req.params.post_id, function(err, post) {
if (err)
res.send(err);
res.json(post);
});
})
// update the post with that id
.put(function(req, res) {
Post.findById(req.params.post_id, function(err, post) {
if (err)
res.send(err);
post.postTitle = req.body.postTitle;
// save the post
post.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'post updated!' });
});
});
})
// deletes the post with that id
.delete(function(req, res) {
Post.remove({
_id: req.params.post_id
}, function(err, post) {
if (err) {
res.send(err);
}
res.json({ message: 'post deleted!' });
});
});
}
You need to add the 'return' so that you don't reply twice.
// save post and check for errors
post.save(function(err) {
if (err) {
return res.send();
}
res.json({ message: 'post created!' });
});
That particular error message is pretty much always caused because of a timing error in the handling of an async response that causes you to attempt to send data on a response after the response has already been sent.
It usually happens when people treat an async response inside an express route as a synchronous response and they end up sending data twice.
One place I see you would get this is in any of your error paths:
When you do this:
// save post and check for errors
post.save(function(err) {
if (err)
res.send();
res.json({ message: 'post created!' });
});
If post.save() generates an error, you will do res.send() and then you will do res.json(...) after it. Your code needs to have a return or an else so when there's an error you don't execute both code paths.
So, this can happen in Express when attempting to send res.end twice which res.send and res.json both do. In your if(err) block you'll want to return res.send() as res.send runs asynchronously and res.json is getting called as well. I'm wondering if you're getting an error in your delete route? Hope this helps.
Best!
You are using res.send() or res.json() twice in the same request
this send the headers first, followed by body of the response and then headers again.
req.next is usually not a function, next is rather passed as a third argument of the middleware. Use that if you want to drop to the next middleware. (assuming you are using Express framework)
Just for the sake of completeness I will also mention that:
Sometime problem may be in a the middleware you may be using by calling
app.use.
After checking for obvious errors as mentioned in previous answers:
You should remove all the app.use statement then reintroduce them one by one, to find problematic module.
If you are using res.send() inside any loop, then you need to break it after the use of res.send(). So that it won't allow resetting of the res headers again and again.
for e.g :
for(){
if(){
res.send();
break;
}
else(){
res.send();
break;
}
}
In my case this is the problem and I solved it like this.
Hope it may help someone in future.
Thanks
For a quick fix you can just check res.finished before calling res.send():
if (!res.finished)
res.send()