NodeJs throws: Cannot post - error message - node.js

I always receive the following error message from NodeJs when trying to get some content via a POST request. <-- This problem is solved.
I would like to get two fields from the database now: name and levels.
Here are the methods:
mongodb (courses):
_id: 12345
teacherId: 9876
userId: 567
name: "admin"
levels: "Advance"
route:
router.get('/course/:userid/showCourses', courseController.showCourseById)
controller:
const showCourseById = async (req, res, next)=>{
try {
let userId = req.params.userId || {};
const course = await courseService.getCourseById(userId);
res.json(course);
} catch (error) {
res.status(500).json({error: error})
}
}
service:
function courseService() {
function getCourseById(userId) {
try {
await courseModel.findById({userId: new ObjectId(userId)}, 'name levels', function(err, items){
if(err) return next(err);
res.send(items);
});
} catch (error) {
console.log(`Course not found. ${error}`)
}
}
return {
getCourseById: getCourseById
}
}
And this is my Postman request
https://xyz/api/course/12345fabe3bd0a386d0962e77
Now, after changing router.post to router.get, I am able to call the method via Postman, however, it returns the login webpage

Related

findById request, cant find my data in mongodb collection

I am creating URL Shortener Microservice application.I have a mongodb cluster that i save my all url links. I am successfully connect to database.I am making post request to save my posted url. Related code is here
app.post('/api/shorturl', (req, res) => {
const bodyUrl = req.body.url;
const something = dns.lookup(
urlParser.parse(bodyUrl).hostname,
(error, address) => {
if (!address) {
res.json({ error: 'Invalid URL' });
} else {
const url = new Url({ url: bodyUrl });
url.save((err, data) => {
res.json({
original_url: data.url,
short_url: data.id,
});
});
}
}
);
});
So, I can save my new url in database succesfully.Here also related cluster after post request
But my problem is with get request. I dont know why i cant find the url links by id. Here also my get request
app.get('/api/shorturl/:id', (req, res) => {
// const id = req.body.id;
Url.findById({ _id: req.body.id }, (err, data) => {
if (!data) {
res.json({ error: 'Invalid URL' });
} else {
res.redirect(data.url);
}
});
});
You need to either use:
Url.findOne({ _id: req.params.id }, (err, data) => {
if (!data) {
res.json({ error: 'Invalid URL' });
} else {
res.redirect(data.url);
}
});
or:
Url.findById(req.params.id, (err, data) => {
if (!data) {
res.json({ error: 'Invalid URL' });
} else {
res.redirect(data.url);
}
});
findOne takes an object as the argument (like you have).
findById just takes the ID as the argument.
You seem to be combining the two options.
Edit: I found another issue with your code, you are trying to pull the id from req.body.id, but in this case, you need to use req.params.id. The code in my post has been updated.

how do I update an object in Sequelize

I am new to Sequelize, and I'm trying to update an object, but it's not working. here is my code
const updateEmployee = async (req, res) =>{
let {full_name, email, phone_number, address} = req.body
const id = req.params.id;
Employee.findOne({
where: { id: id }
})
.then(employee => {
employee.update({
full_name: full_name.full_name,
email: email.email,
phone_number: phone_number.phone_number,
address: address.address
})
})
}
please assist !!
You can use the update() method and add the search scope as second argument. The update() method is a Promise that returns an array with with one or two elements. The first element is always the number of affected rows. See the sequelize API documentation for more details on the update() method.
Your code should look something like this. I have not tested this so you might need to tweak the code a bit:
updateUser: async (req, res) => {
try {
await employee.update(req.body, {
where: {
id: req.body.id
}
})
.then((result) => {
// check the first element in the array if there are rows affected
if (result[0] > 0) {
res.status(200).send({ message: 'data found' });
} else {
return res.status(422).send({ message: 'no data found' });
}
})
}
catch(error) {
console.log(error);
return res.status(500).send({ message: 'updating user failed' });
}
}
When you are using async function. It is best to use await also don't use promise based format this in below api first I am finding user with that id from database if its present it ill update user else it will throw error that there is no data with that id
updateUser: async (req, res) => {
try {
let data = await employee.findOne({
where: {
id: req.body.id
}
});
if (data) {
await employee.update(req.body, { where: { id: req.body.id } });
return res.status(200).send({message: data found});
}
else {
return res.status(422).send({message: no data found});
}
} catch (err) {
console.log(err)
return res.status(500).send({message: Internal server error);
};
}

Err: Cannot POST /api/success

I am trying to send a POST request but it seems like the route isn't working based off the error. However, I get the value of req.body.entries logged in my console so it has to be working. When I send a GET request the browser sits and loads. The same thing happens in Postman. I am trying to figure out why I get an error on the POST request and the GET request sits. Thank you in advance.
index.js
const successRoute = require("./routes/success");
app.use("/api/success", successRoute);
success.js
router.get(
"/",
basicAuth({
users: { username: "password" },
}),
async function (req, res) {
try {
const entry = await Entry.find({});
res.sendStatus(entry);
} catch (err) {
res.sendStatus({ msg: "oops something went wrong" });
}
}
);
router.post("/", async (req, res, next) => {
try {
//console.log(req.body);
const { store, entries } = req.body;
Entry.findOneAndUpdate(
{ _id: store },
{ $set: { entries: +req.body.entries } },
{ new: true },
(err, doc) => {
if (err) {
console.log(err);
}
console.log(req.body.entries);
next();
}
);
} catch (err) {
const entry = new Entry({
_id: store,
entries: req.body.entries,
});
await entry.save();
res.sendStatus(200);
next();
}
});
I think the problem is, inside your router.post(), you're not sending any response, you only call next(). I don't see any next route for the request.
I'd recommend something like this:
router.post("/", async (req, res, next) => {
try {
//console.log(req.body);
const { store, entries } = req.body;
Entry.findOneAndUpdate(
{ _id: store },
{ $set: { entries: +req.body.entries } },
{ new: true },
(err, doc) => {
// throw the error and catch later
if (err)
throw err;
console.log(req.body.entries);
// send response instead of calling next()
res.sendStatus(200);
}
);
} catch (err) {
const entry = new Entry({
_id: store,
entries: req.body.entries,
});
await entry.save();
// send response
res.sendStatus(200);
// next(); // don't call next unless next route defined
}
});

Cast to ObjectId failed for value ... at path "_id" for model but I am not doing any query

I have an express route that gets call with axios from the frontend. The thing is, not matter what I put into the route I always get the same error:
"Cast to ObjectId failed for value "getTodosMisProductos" at path "_id" for model "local""
I'm not doing any query to mongoose in that route but in any other route where I make a query everything works fine.
I've checked the middleware but there is not any query to mongoose
getTodosMisProductos
router.get("/getTodosMisProductos", auth, async (req, res) => {
/*
try {
const data = await Local.findOne({ user: req.user.id }).populate("products.producto");
console.log(data);
if (!data) {
return res
.status(404)
.json({ errors: [{ msg: "No se encontro el local" }] });
}
return res.status(200).json(data.products);
} catch (error) {
console.log(req.user.id);
console.error("error en llamado");
return res.status(500).send("Server Error");
}
*/
console.log("algo");
return res.status(200).json({ msg: "success" });
});
the code commented is the code I need to use, I changed it for testing purposes but even with that simple new code I get the same error.
auth middleware
const jwt = require("jsonwebtoken");
const config = require("config");
module.exports = function (req, res, next) {
// Get token from header
const token = req.header("x-auth-token");
// Check if not token
if (!token) {
return res
.status(401)
.json({ msg: "No tienes autorización para hacer esto" });
}
// Verify token
try {
const decoded = jwt.verify(token, require("../config/keys").jwtSecret);
req.user = decoded.user;
next();
} catch (error) {
res.status(401).json({ msg: "El token es inválido" });
}
};
action from where the route gets called
export const getAllProductos = () => async (dispatch) => {
try {
console.log("Esto se llama");
const res = await axios.get("/api/local/getTodosMisProductos/");
dispatch({
type: SET_PRODUCTS,
payload: res.data,
});
} catch (err) {
const errors = err.response.data.errors;
if (errors) {
errors.forEach((error) => dispatch(setAlert(error.msg, "danger")));
}
}
};
The response status is always 500 (Internal Server Error)
EDIT
//#route GET api/local/:id
//#desc obtener local por id
//#access private
router.get("/:id", auth, async (req, res) => {
try {
const local = await Local.findById(req.params.id);
if (!local) {
return res
.status(404)
.json({ errors: [{ msg: "No se encontro el local" }] });
}
return res.status(200).json(local);
} catch (error) {
console.error(error.message);
res.status(500).send("Server Error");
}
});
You have another route that also match /api/local/getTodosMisProductos/
Apparently it got matched with /api/local/:id,
where you get req.params.id = "getTodosMisProductos" and got passed down to await Local.findById(req.params.id)
And mongoose can't convert "getTodosMisProductos" to ObjectId, hence the error.
The order in which you declare the route affects the matching priority.
The order is first comes first serves, so make sure you declare /api/local/addProducto or any other routes that starts with /api/local/ before declaring /api/local/:id

NodeJS/MongoDB - Error: Can't set headers after they are sent

I got this helper function:
const Account = require('../models/account');
exports.sendInvites = (accountIds, invite, callback) => {
if (!accountIds) {
callback('No account ids provided', null, null);
return;
}
accountIds.forEach((id) => {
Account.findOneAndUpdate({_id: id}, {$push: {organisationInvites: invite}}, callback);
});
};
Then I have this route:
router.post('/organisations', auth.verifyToken, (req, res, next) => {
const organisation = new Organisation({
name: req.body.name,
email: req.body.email,
admins: [req.body.createdBy],
createdBy: req.body.createdBy
});
organisation.save((err, organisation) => {
if (err) {
return res.status(500).json({
error: err,
data: null
});
}
organisationUtils.sendInvites(req.body.invites, {
inviter: req.body.createdBy,
organisation: organisation._id
}, (err, account, response) => {
if (err) {
return res.status(500).json({
error: err,
data: null
});
}
res.json({
error: null,
data: organisation
});
});
});
});
I get a Error: Can't set headers after they are sent. error for the
res.json({
error: null,
data: organisation
});
part but I can't understand why this is happening. I tried looking at the accepted answer here Error: Can't set headers after they are sent to the client, did some digging but couldn't find any specific reason still what's happening in my particular example above. Any ideas?
You are calling the callback multiple times, and so res.json multiple times. Gather the data from all database request then perform an unique res.json.
accountIds.forEach((id) => {
Account.findOneAndUpdate(
{_id: id},
{$push: {organisationInvites: invite}},
callback,
);
});
Something like :
var allData = [];
var nbRequestDone = 0;
var waitAllCallback = function (data, err) {
if (err) {
callback(err);
nbRequestDone = accountIds.length;
return;
}
nbRequestDone += 1;
allData.push(data);
if (nbRequestDone === accountIds.length) {
callback(false, allData);
}
};
accountIds.forEach((id) => {
Account.findOneAndUpdate(..., waitAllCallback);
});
this video covers the Error regarding "Error: Can't set headers after they are sent".
https://www.youtube.com/watch?v=rKTlakY8j2M
In summary of the video, this error shows up when you have an extra callback in your code. Hope this helps. Been struggling with this one too for quite some time.

Resources