I am at a beginner level with the MEAN stack, trying to work on the following tutorial: adrianmejia.com/blog/2014/10/01/creating-a-restful-api-tutorial-with-nodejs-and-mongodb/. I am using Cloud 9 online IDE.
Part of the tutorial involves testing database POST using curl and Postman. I successfully post a GET request, which at this point in the tutorial gives med an empty array.
I use
curl -XGET myc9urlhere:8080/todos
- with success (getting [])
And try curl -XPOST myc9urlhere:8080/todos -d 'name=Somename&completed=false¬e=somenote'
- failing
The stacktrace is as follows:
ValidationError: Todo validation failed
at MongooseError.ValidationError (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/error/validation.js:23:11)
at model.Document.invalidate (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/document.js:1486:32)
at model.Document.set (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/document.js:753:10)
at model._handleIndex (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/document.js:596:14)
at model.Document.set (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/document.js:556:24)
at model.Document (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/document.js:68:10)
at model.Model (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/model.js:47:12)
at new model (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/model.js:3250:13)
at /home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/model.js:1864:51
at /home/ubuntu/workspace/todo-api/node_modules/mongoose/node_modules/async/internal/parallel.js:27:9
at eachOfArrayLike (/home/ubuntu/workspace/todo-api/node_modules/mongoose/node_modules/async/eachOf.js:57:9)
at exports.default (/home/ubuntu/workspace/todo-api/node_modules/mongoose/node_modules/async/eachOf.js:9:5)
at _parallel (/home/ubuntu/workspace/todo-api/node_modules/mongoose/node_modules/async/internal/parallel.js:26:5)
at parallelLimit (/home/ubuntu/workspace/todo-api/node_modules/mongoose/node_modules/async/parallel.js:85:26)
at /home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/model.js:1882:5
at Function.create (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/model.js:1852:17)
A small note is that I have also tried this using the Chrome extension Postman. The tutorial says I must use x-www-form-urlencoded
which gives the same error returned. See screenshot. And if I turn to the form-data setting instead, I actually succeed in inserting some data into the database, but just bogus stuff. See the second screenshot.
I have really tried to research myself - maybe this tutorial is not the greatest place to start either :). Below I will include some details on the code.
Thanks a lot for any help solving this.
Identical to the tutorial, I have created a Model for a todo-list item, as shown (Todo.js):
var mongoose = require('mongoose');
var TodoSchema = new mongoose.Schema({
name: String,
completed: Boolean,
note: String
});
module.exports = mongoose.model('Todo', TodoSchema);
Now in my express routing file todos.js I have the following code:
var express = require('express');
var router = express();
//express.Router() was the original here, that failed on router.get
//as router was then undefined for some reason.
var Todo = require('../models/Todo.js');
/* GET /todos listing. */
router.get('/', function(req, res, next) {
Todo.find(function (err, todos) {
if (err) return next(err);
res.json(todos);
});
});
/* POST /todos */
router.post('/', function(req, res, next) {
Todo.create(req.body, function (err, post) {
if (err) return next(err);
res.json(post);
});
});
module.exports = router;
Because I do not know exactly what is wrong here I will also post an extract of my app.js showing my database connection
var routes = require('./routes/index');
var users = require('./routes/users');
var todos = require('./routes/todos');
var app = express();
// load mongoose package
var mongoose = require('mongoose');
// Use native Node promises
mongoose.Promise = global.Promise;
// connect to MongoDB
mongoose.connect('mongodb://'+process.env.IP+'/todo-api')
.then(() => console.log('connection succesful'))
.catch((err) => console.error(err));
app.use('/', routes);
app.use('/users', users);
app.use('/todos', todos);
And the package-json that was generated (I am using Cloud 9 IDE)
{
"name": "application-name",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node app.js"
},
"dependencies": {
"ejs": "*",
"express": "3.2.6",
"mongoose": "^4.7.6"
}
}
I think the main problem you're encountering here is that all post parameters are strings. This ends up being fine for the
name
andnote
fields of youTodoSchema
, but will break when it comes to thecompleted
field, since it is boolean. To address this, try converting the string to a boolean before creating the ToDo entry.Also, the reason that the bogus post worked is because you aren't validating your post data. Consider making sure that the post data coming in though your route has all of the required fields, and doesn't contain anything dangerous.