this is my first project in node js and i created an API that have get, delete, update, and post. i tested GET and response 200 ok but POST is 400 bad request i don't know why ... i tested this in postman and vue js too but same result
below is my code in nodeJs: can someone please tell me what is the problem?
thanks in advance
//question.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const questionSchema = new Schema({
questionTitle: {
type: String,
required: true,
},
is_solver_selected : {
type: Boolean,
default : false,
},
reviewed: {
type: Boolean,
default : false,
},
question_file_path: {
type: String,
required: true
},
description : {
type : String,
required : true
},
solutions : [
{
type: Schema.Types.ObjectId,
ref:"Solution",
default : []
}
],
owner : {
type : Schema.Types.ObjectId,
ref : "User",
required : true
},
categories : [{
type : Schema.Types.ObjectId,
ref : "Category",
required : true
}],
answered: {
type: Boolean,
default : false,
},
budget : {
type : String,
required : true
}
}, { timestamps: true });
const Question = mongoose.model('Question', questionSchema);
module.exports = Question;
//questionApiController
const Category = require('../models/category');
const Question = require('../models/question');
const User = require('../models/user');
const validators = require('../validators');
let questionApiController = {
// Get a single question
get_question : async (req , res) => {
const id = req.params.id;
try {
const question = await Question.findById(id,(err, question) => {
if (err) return res.status(400).json({response : err});
res.status(200).json({response : question})
}).populate('owner', 'username').populate('categories').populate({
path : "solutions",
populate : {path : "solver_candidate" , select : "username"}});
} catch (err) {
res.status(400).json(err);
}
},
// Get all the questions
get_questions: async (req , res) => {
try {
const questions = await Question.find((err, questions) => {
if (err) return res.status(400).json({response : err});
res.status(200).json({response : questions})
}).sort({ createdAt: -1 }).populate('owner', 'username').populate('categories').populate({
path : "solutions",
populate : {path : "solver_candidate" , select : "username"}});
} catch (err) {
res.status(400).json(err);
}
},
// Create a question
create_question : async (req , res) => {
const {error} = validators.postQuestionValidation(req.body);
if(error) return res.status(400).json({ "response" : error.details[0].message})
try {
const question = await new Question(req.body);
User.findByIdAndUpdate(req.body.owner)
.then(result => {
result.questions.push(question._id)
result.save((err, categories) => {
if (err) return res.status(400).json({response : {error : err , explanation : " Error binding to the user !"}});
});
})
.catch(err => {
res.status(400).json({response: err });
});
req.body.categories.forEach(element => {
Category.findById(element).then(result => {
}).catch(err => {
res.status(400).json({response : err });
})
})
question.save((err, question) => {
if (err) return res.status(400).json({response : err});
res.status(200).json({response : " Question created Successfully"})
});
} catch (err) {
res.status(400).json(err);
}
},
// Delete question
delete_question : async (req , res) => {
const id = req.params.id;
var questionExist = false;
var userId ;
const question = await Question.findById(id).then(result => {
questionExist = true;
userId = result.owner;
}).catch(err => {
questionExist = false;
res.status(400).json({response : err });
});
if(questionExist){
try {
Question.findByIdAndRemove(id ,(err, question) => {
// As always, handle any potential errors:
if (err) return res.json({response : err});
// We'll create a simple object to send back with a message and the id of the document that was removed
// You can really do this however you want, though.
const response = {
message: "Question successfully deleted",
id: question._id
};
return res.status(200).json({response : response });
});
User.findByIdAndUpdate(userId)
.then(result => {
let pos = result.questions.indexOf(question._id);
result.questions.splice(pos,1);
result.save((err, categories) => {
if (err) return res.status(400).json({response : {error : err , explanation : "Error binding unbinding from the user"}});
});
})
.catch(err => {
res.json({response: err });
});
} catch (err) {
res.status(400).json(err);
}
}
else {
return res.status(400).send( { "response" : "A question with that id was not find."});
}
},
// Update question
update_question : async (req , res) => {
const id = req.params.id;
Question.findByIdAndUpdate(id,req.body,
function(err, result) {
if (err) {
res.status(400).json({response : err});
} else {
res.status(200).json({response : "Question Updated"});
console.log(result);
}
})
},
bind_question_to_solver : async (req , res) => {
const id = req.params.id;
Question.findByIdAndUpdate(id,{
solver : req.body.solver ,
response_file_path : req.body.response_file_path},function(err, result) {
if (err) {
res.status(400).json({response : err});
} else {
res.status(200).json({response : "Question Bind to Solver"});
//Update the user solver by adding the question id in its quesion array1
console.log(result);
}
})
},
// Get question's questions
get_question_categories : async (req , res) => {
const id = req.params.id;
try {
const question_categories = await Question.findById(id).populate("categories")
console.log(question_categories)
res.json(question_categories)
} catch (err) {
console.log(err);
res.json(err);
}
}
}
module.exports = questionApiController
//question controller
const Question = require('../models/question');
const question_index = (req, res) => {
Question.find().sort({ createdAt: -1 })
.then(result => {
res.render('index', { questions: result, title: 'All questions' });
})
.catch(err => {
console.log(err);
});
}
const question_details = (req, res) => {
const id = req.params.id;
Question.findById(id)
.then(result => {
res.render('details', { question: result, title: 'Question Details' });
})
.catch(err => {
console.log(err);
res.render('404', { title: 'Question not found' });
});
}
const question_create_get = (req, res) => {
res.render('create', { title: 'Create a new question' });
}
const question_create_post = (req, res) => {
const question = new Question(req.body);
question.save()
.then(result => {
res.redirect('/questions');
})
.catch(err => {
console.log(err);
});
}
const question_delete = (req, res) => {
const id = req.params.id;
Question.findByIdAndDelete(id)
.then(result => {
res.json({ redirect: '/questions' });
})
.catch(err => {
console.log(err);
});
}
module.exports = {
question_index,
question_details,
question_create_get,
question_create_post,
question_delete
}
sent request:
Post http://localhost:9000/questions/api/add content-type: application/json
{ "description": "d", "questionTitle": "ddd", "categories":"ddd", "question_file_path":"d.pdf", "budget":"d", "owner":"bla",
}
`error message': HTTP/1.1 400 Bad Request
SyntaxError: Unexpected token } in JSON at position 160
at JSON.parse ()
at parse (C:\Users\saad\Desktop\APi-master-nodejs\node_modules\body-parser\lib\types\json.js:89:19)
at C:\Users\saad\Desktop\APi-master-nodejs\node_modules\body-parser\lib\read.js:121:18
at invokeCallback (C:\Users\saad\Desktop\APi-master-nodejs\node_modules\raw-body\index.js:224:16)
at done (C:\Users\saad\Desktop\APi-master-nodejs\node_modules\raw-body\index.js:213:7)
at IncomingMessage.onEnd (C:\Users\saad\Desktop\APi-master-nodejs\node_modules\raw-body\index.js:273:7)
at IncomingMessage.emit (events.js:327:22)
at endReadableNT (_stream_readable.js:1327:12)
at processTicksAndRejections (internal/process/task_queues.js:80:21)
CodePudding user response:
based on your updated post, i would start to fix the provided json. because as the response says, it is invalid. JSON does not have trailing comma at the end of the last entry.
{ "description": "d", "questionTitle": "ddd", "categories":"ddd", "question_file_path":"d.pdf", "budget":"d", "owner":"bla"}
would be fine.
CodePudding user response:
Check why-body-parser-json-is-not-working-showing-syntaxerror-unexpected-token post, you have a similar problem.
You are sending ,
symbol after last field in the json object which is not expected by the body-parser
when you are sending content-type: application/json