Cannot POST (Commenting on a post) | Mongodb with mongoose - node.js

I'm building an app in NodeJS/Express combined with Mongodb, where I want to be able to comment to a post but I keep getting a 404 not found.
I setup the models and routes in my server.js and also setup the 'ref' between the two but this is the response I keep getting:
And as you can see with the following, the 'capture' aka 'post' does actually exist:
Edit: Made some changes to my initial code with the answers that Zen gave me.
This is my code:
-server.js
// Init Express Web Framework
var express = require('express');
var app = express();
var path = require('path');
// Set view engine to EJS & set views directory
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
app.set('views', path.resolve(__dirname, 'client', 'views'));
app.use(express.static(path.resolve(__dirname, 'client')));
// Database Connection
var mongoose = require('mongoose');
var configDB = require('./server/config/database.js');
require('./server/routes/capture');
require('./server/routes/comment');
mongoose.connect(configDB.url);
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.text());
app.use(bodyParser.json({ type: 'application/json'}));
// Main route
app.get('/', function(req, res){
res.render('index.html');
});
// API
var api = express.Router();
require('./server/routes/capture')(api);
require('./server/routes/comment')(api);
app.use('/api', api);
// Port Settings
app.listen(process.env.PORT || 3000, process.env.IP);
console.log('Listening on port ' + process.env.PORT);
-capture.js model:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var captureSchema = Schema({
birdname: {type: String, required: true},
place: String,
userId: String,
author: String,
picture: Schema.Types.Mixed,
created_at: Date,
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Comment'}]
});
module.exports = mongoose.model('Capture', captureSchema);
-capture.js route:
var Capture = require('../models/capture');
module.exports = function(router) {
router.post('/captures', function(req, res){
var capture = new Capture();
capture.birdname = req.body.birdname;
capture.place = req.body.place;
capture.userId = req.body.userId;
capture.author = req.body.author;
capture.picture = req.body.picture;
capture.created_at = new Date();
capture.save(function(err, data){
if(err)
throw err;
console.log(req.body);
res.json(data);
});
});
router.get('/captures', function(req, res){
Capture.find({}, function(err, data){
if(err)
throw err;
res.json(data);
});
});
router.delete('/captures', function(req, res){
Capture.remove({}, function(err){
res.json({result: err ? 'error' : 'ok'});
});
});
router.get('/captures/:id', function(req, res){
Capture.findOne({_id: req.params.id}, function(err, data){
if(err)
throw err;
res.json(data);
});
});
router.delete('/captures/:id', function(req, res){
Capture.remove({_id: req.params.id}, function(err){
res.json({result: err ? 'error' : 'ok'});
});
});
};
-capture.js model:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var commentSchema = Schema({
birdname: String,
body: {type: String, required: true},
userId: {type: String, required: true},
author: {type: String, required: true},
created_at: Date,
capture: [{ type: Schema.Types.ObjectId, ref: 'Capture'}]
});
module.exports = mongoose.model('Comment', commentSchema);
-comment.js route:
var Comment = require('../models/comment');
module.exports = function(router) {
router.post('/captures/:capture/comments', function(req, res, next){
var comment = new Comment();
comment.birdname = req.body.birdname;
comment.body = req.body.body;
comment.userId = req.body.userId;
comment.author = req.body.author;
comment.created_at = new Date();
comment.capture = capture;
comment.save(function(err, comment) {
if (err) { return next(err); }
req.capture.comments.push(comment);
req.capture.save(function(err, capture) {
if (err) { return next(err); }
res.json(comment);
});
});
});
};
Any help is much appreciated..
Thanks

I would work with one route script, seeing that your comments are attached to the post.
You also have to add a Map logic to the route parameters for cature and comment.
Try the following:
var Capture = require('../models/capture');
var Comment = require('../models/comment');
module.exports = function(router) {
router.post('/captures', function(req, res){
var capture = new Capture();
capture.birdname = req.body.birdname;
capture.place = req.body.place;
capture.userId = req.body.userId;
capture.author = req.body.author;
capture.picture = req.body.picture;
capture.created_at = new Date();
capture.save(function(err, data){
if(err)
throw err;
console.log(req.body);
res.json(data);
});
});
router.get('/captures', function(req, res){
Capture.find({}, function(err, data){
if(err)
throw err;
res.json(data);
});
});
router.delete('/captures', function(req, res){
Capture.remove({}, function(err){
res.json({result: err ? 'error' : 'ok'});
});
});
// Map logic to route parameter 'capture'
router.param('capture', function(req, res, next, id) {
var query = Capture.findById(id);
query.exec(function (err, capture) {
if (err) { return next(err); }
if (!capture) { return next(new Error("can't find post")); }
req.capture = capture;
return next();
});
});
// Map logic to route parameter 'comment'
router.param('comment', function (req, res, next, id) {
var query = Comment.findById(id);
query.exec(function (err, comment) {
if (err) { return next(err); }
if (!comment) { return next(new Error("can't find comment")); }
req.comment = comment;
return next();
});
});
router.get('/captures/:id', function(req, res){
Capture.findOne({_id: req.params.id}, function(err, data){
if(err)
throw err;
res.json(data);
});
});
router.delete('/captures/:id', function(req, res){
Capture.remove({_id: req.params.id}, function(err){
res.json({result: err ? 'error' : 'ok'});
});
});
router.post('/captures/:capture/comments', function(req, res, next){
var comment = new Comment();
comment.birdname = req.body.birdname;
comment.body = req.body.body;
comment.userId = req.body.userId;
comment.author = req.body.author;
comment.created_at = new Date();
comment.capture = req.capture;
comment.save(function(err, comment) {
if (err) { return next(err); }
req.capture.comments.push(comment);
req.capture.save(function(err, capture) {
if (err) { return next(err); }
res.json(comment);
});
});
});
};

The status code is 404. Apparently, no corresponding router is found. The problem is that you export an "init" function in comment.js route. When you require the comment router in server.js, nothing happens.
// API
var api = express.Router();
require('./server/routes/capture')(api);
// you have forgotten it
require('./server/routes/comment')(api);
app.use('/api', api);
BTW, there is no need putting capture into req.body when you're posting to '/captures/:capture/comments', since you can get :capture by using const capture = req.params.capture;.

Related

Nodejs Uploading Images

Hey am making a website that will show the articles and the relevant images at the same time. I have already been uploading image files but I cannot show it in my page.
These are my relevant codes:
Article Module:
let mongoose = require('mongoose');
let articleSchema = mongoose.Schema({
title:{
type: String,
required: true
},
author:{
type:String,
required:true
},
body:{
type:String,
required:true
},
img:{
type:String,
required:true
}
});
let Article = module.exports = mongoose.model('Article', articleSchema);
User Module:
let mongoose = require('mongoose');
// User Schema
let UserSchema = mongoose.Schema({
name:{
type: String,
required: true
},
email:{
type: String,
required: true
},
username:{
type: String,
required: true
},
password:{
type: String,
required: true
}
});
let User = module.exports = mongoose.model('User', UserSchema);
Article.js:
const express = require('express');
const router = express.Router();
const multer = require('multer');
// Article Model
let Article = require('../models/article');
// User Model
let User = require('../models/user');
router.get('/sonuc', function(req, res){
if(req.query.search) {
const regex = new RegExp(escapeRegex(req.query.search), 'gi');
Article.find({"title": regex}, function(err, articles) {
if(err) {
console.log(err);
} else {
res.render("sonuc", {
articles: articles
});
}
});
}
});
function escapeRegex(text) {
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
};
// Add Route
router.get('/add', ensureAuthenticated, function(req, res){
res.render('add_article', {
title:'Add Article'
});
});
const upload = multer({dest: __dirname + '/uploads'});
// Add Submit POST Route
router.post('/add',upload.single('img'), function(req, res){
req.checkBody('title','Title is required').notEmpty();
//req.checkBody('author','Author is required').notEmpty();
req.checkBody('body','Body is required').notEmpty();
// Get Errors
let errors = req.validationErrors();
if(errors){
res.render('add_article', {
title:'Add Article',
errors:errors
});
} else {
var article = new Article({
title: req.body.title,
author: req.user._id,
img: '/uploads/' + req.file.filename,
body: req.body.body,
});
article.save(function(err){
if(err){
console.log(err);
return;
} else {
res.render('add_article', {
});
}
});
}
});
// Load Edit Form
router.get('/edit/:id', ensureAuthenticated, function(req, res){
Article.findById(req.params.id, function(err, article){
/*if(article.author != req.user._id){
req.flash('danger', 'Not Authorized');
return res.redirect('/');
}*/
res.render('edit_article', {
title:'Edit Article',
article:article
});
});
});
// Update Submit POST Route
router.post('/edit/:id', function(req, res){
let article = {};
article.title = req.body.title;
article.author = req.body.author;
article.body = req.body.body;
let query = {_id:req.params.id}
Article.update(query, article, function(err){
if(err){
console.log(err);
return;
} else {
req.flash('success', 'Article Updated');
res.redirect('/');
}
});
});
// Delete Article
router.delete('/:id', function(req, res){
if(!req.user._id){
res.status(500).send();
}
let query = {_id:req.params.id}
Article.findById(req.params.id, function(err, article){
if(article.author != req.user._id){
res.status(500).send();
} else {
Article.remove(query, function(err){
if(err){
console.log(err);
}
res.send('Success');
});
}
});
});
// Get Single Article
router.get('/:id', function(req, res){
Article.findById(req.params.id, function(err, article){
//User.findById(article.author, function(err, user){
res.render('article', {
article:article,
imagePath: user.img,
author: user.name
});
});
});
//});
// Access Control
function ensureAuthenticated(req, res, next){
if(req.isAuthenticated()){
return next();
} else {
req.flash('danger', 'Please login');
res.redirect('/users/login');
}
}
module.exports = router;
article.pug:
extends layout
block content
br
h1= article.title
//h5 Written by #{author}
p= article.body
img(src=imagePath, alt='img')
hr
if user
if user.id ==article.author
a.btn.btn-default(href='/articles/edit/'+article._id) Edit
a.btn.btn-danger.delete-article(href='#',data-id=article._id) Delete
Still I cannot understan why that these codes are not working. I am waiting your supports. Every answer will be appreciated.
My App.js:
const express = require('express');
const ejs = require('ejs');
const path = require('path');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const expressValidator = require('express-validator');
const flash = require('connect-flash');
const session = require('express-session');
const passport = require('passport');
config = require('./config/database');
const multer = require('multer');
mongoose.connect(config.database);
let db = mongoose.connection;
// Check connection
db.once('open', function(){
console.log('Connected to MongoDB');
});
// Check for DB errors
db.on('error', function(err){
console.log(err);
});
// Init App
const app = express();
// Bring in Models
let Article = require('./models/article');
// EJS
app.set('view engine', 'ejs');
// Public Folder
app.use(express.static('./public'));
// Load View Engine
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
// Body Parser Middleware
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());
// Set Public Folder
app.use(express.static(path.join(__dirname, 'public')));
// Express Session Middleware
app.use(session({
secret: 'keyboard cat',
resave: true,
saveUninitialized: true
}));
// Express Messages Middleware
app.use(require('connect-flash')());
app.use(function (req, res, next) {
res.locals.messages = require('express-messages')(req, res);
next();
});
// Express Validator Middleware
app.use(expressValidator({
errorFormatter: function(param, msg, value) {
var namespace = param.split('.')
, root = namespace.shift()
, formParam = root;
while(namespace.length) {
formParam += '[' + namespace.shift() + ']';
}
return {
param : formParam,
msg : msg,
value : value
};
}
}));
// Passport Config
require('./config/passport')(passport);
// Passport Middleware
app.use(passport.initialize());
app.use(passport.session());
app.get('*', function(req, res, next){
res.locals.user = req.user || null;
next();
});
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads')
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
})
const upload = multer({ storage: storage })
// Check File Type
function checkFileType(file, cb){
// Allowed ext
const filetypes = /jpeg|jpg|png|gif/;
// Check ext
const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
// Check mime
const mimetype = filetypes.test(file.mimetype);
if(mimetype && extname){
return cb(null,true);
} else {
cb('Error: Images Only!');
}
}
// Home Route
app.get('/', function(req, res){
Article.find({}, function(err, articles){
if(err){
console.log(err);
} else {
res.render('index', {
title:'Articles',
articles: articles
});
}
});
});
app.get('/sonuc', function(req, res){
if (req.query.search) {
const regex = new RegExp(escapeRegex(req.query.search), 'gi');
Article.find({"title": regex}, function(err, articles) {
if(err) {
console.log(err);
} else {
res.render("index", {
articles: articles
});
}
});
}
});
function escapeRegex(text) {
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
};
// Route Files
let articles = require('./routes/articles');
let users = require('./routes/users');
app.use('/articles', articles);
app.use('/users', users);
// Start Server
app.listen(3000, function(){
console.log('Server started on port 3000...');
});
You have to pass in the path to the img tag for it to render your image.
You have specified /upload to be the folder, so just put that into the src attribute of the img tags.
extends layout
block content
br
h1= article.title
//h5 Written by #{author}
p= article.body
img(src=imagePath, alt='img')
GET route fix:
Article.findById(req.params.id, function(err, article){
//You commented this line that's why user is undefined
User.findById(article.author, function(err, user){
res.render('article', {
article:article,
imagePath: article.img, //Should be article.img
author: user.name
})

How to fix 'Parsing error: Unexpected token' in Node?

On saving the code (Node JS), getting the error, 'Parsing error: Unexpected Token'
Note - Mongo connected
Tried adjusting the curly brackets and semicolon, still not working
What am I doing wrong?
Below is the code,
var express = require("express");
var app = express();
var bodyParser = require("body-parser");
var mongoose = require("mongoose");
//connecting and creating a database
mongoose.connect("mongodb://localhost/yelp_camp");
app.use(bodyParser.urlencoded({extended: true}));
app.set("view engine", "ejs");
//schema setup
var campgroundSchema = new mongoose.Schema({
name: String,
url: String
});
var Campground = mongoose.model("Campground", campgroundSchema);
Campground.create( {name: "CampAliBaba", image:"https://photosforclass.com/download/flickr-7121865553"},
function(err, campground){
if (err){
console.log(err);
}
else {
console.log("newly created campground");
console.log(campground);
}
});
var campgrounds = [
{name: "Jenny Lake", image:"https://farm2.staticflickr.com/1424/1430198323_c26451b047.jpg"},
{name: "RichardBH", image:"https://photosforclass.com/download/flickr-7626464792"},
{name: "CampAliBaba", image:"https://photosforclass.com/download/flickr-7121865553"},
{name: "CampAliBabaHai", image:"https://photosforclass.com/download/flickr-2770447094"},
{name: "CampAliBabaHaiYe", image:"https://photosforclass.com/download/flickr-2602356334"},
];
app.get("/", function(req, res){
res.render("landing");
});
app.get("/campgrounds", function(req, res){
Campground.find({}, function(err, allCampgrouns){
if(err){
console.log(err)
}
else {
res.render("campgrounds", {campgrounds:allCampgrounds});
}
});
app.post("/campgrounds", function(req, res){
var name = req.body.name
var image = req.body.image
var newcampground = {name: name, image: image}
campgrounds.push(newcampground);
res.redirect("/campgrounds");
});
app.get("/campgrounds/new" , function(req, res){
res.render("new.ejs");
});
app.listen(process.env.PORT, process.env.IP, function(){
console.log("YelpCamp server started!");
});
Expected-
The file should save error-free in order to start the server and run the application
Actual-
Getting above mentioned error
app.get("/campgrounds", function(req, res){
Campground.find({}, function(err, allCampgrouns){
if(err){
console.log(err)
}
else {
res.render("campgrounds", {campgrounds:allCampgrounds});
}
});// missing the closing brackets
});
you have miss the closing tag
On line 55, you should have an extra });
app.get("/campgrounds", function(req, res){
Campground.find({}, function(err, allCampgrouns){
if(err){
console.log(err)
}
else {
res.render("campgrounds", {campgrounds:allCampgrounds});
}
});
});

Type error in mean stack post method

MEAN Stack
I keep getting
TypeError: Cannot read property 'first_name' of undefined
when trying to execute this code (all variables, including modules are defined in other parts of the code). While using GET Method, my code is working fine. But for POST Method, it throws error. Attached the screenshot below.
Advance Rest Client POST Method Exception
Added my code below.
Thanks in advance
//app.js
//Importing Modules
var express = require('express');
var mongoose = require('mongoose');
var bodyparser = require('body-parser');
var cors = require('cors');
var path = require('path');
var app = express();
//port Number
const port = 3000;
const route = require('./routes/route');
//Connect to MongoDB
mongoose.connect('mongodb://localhost:27017/contactlist');
//if connected
mongoose.connection.on('connected', () => {
console.log("Mongo DB Connected successfully");
});
//if not connected
mongoose.connection.on('error', (err) => {
if (err) {
console.log('Error in connecting to the MongoDB');
}
});
//adding middleware cors
app.use(cors());
//routes will happen here
app.use('/api', route);
//adding middleware
app.use(bodyparser.json());
//Static files
app.use(express.static(path.join(__dirname, 'public')));
//Testing
app.get('/', (req, res) => {
res.send("Hello Vinoth");
});
app.get('/yahoo', (req, res) => {
res.send("Hello Vinoth");
});
//Connection
app.listen(port, () => {
console.log("Server started at port:" + port);
});
//route.js
const express = require('express');
const router = express.Router();
const Contact = require('../models/contacts');
// retrieving details
router.get('/contacts', (req, res, next) => {
Contact.find(function(err, contacts) {
res.json(contacts);
});
});
// Add Contacts
//Add contact
router.post('/contact', (res, req, next) => {
console.log('Insides');
let newContact = new Contact({
first_name: req.body.first_name,
last_name: req.body.last_name,
phone: req.body.phone
});
newContact.save((err, contact) => {
if (err) {
res.json({
msg: 'Failed to add contact'
});
} else {
res.json({
msg: 'Contact added successfully'
});
}
});
});
// Delete Contacts
router.delete('/contact/:id', (req, res, next) => {
Contact.remove({
_id: req.params.id
}, function(err, result) {
if (err) {
res.json(err);
} else {
res.json(result);
}
});
});
module.exports = router;
//contacts.js
const mongoose = require('mongoose');
const ContactSchema = mongoose.Schema({
first_name: {
type: String,
required: true
},
last_name: {
type: String,
required: true
},
phone: {
type: String,
required: true
}
});
const Contact = module.exports = mongoose.model('Contact', ContactSchema);
Try moving app.use(bodyparser.json()) before app.use('/api', route). Hope this helps.
First of all you need to Declare
//adding middleware
app.use(bodyparser.json());
Before use all routes. So you need to update your app.js like:
//adding middleware
app.use(bodyparser.json());
//routes will happen here
app.use('/api', route);
In additional you need to refactor your route.js
code like this:
//Add contact
router.post('/contact', (res, req, next) => {
const {
first_name,
last_name,
phone
} = req.body;
let newContact = new Contact({
first_name,
last_name,
phone
});
newContact.save((err, contact) => {
if (err) {
res.json({
msg: 'Failed to add contact'
});
} else {
res.json({
msg: 'Contact added successfully'
});
}
});
});

my post request using nodejs express to mongodb database doesn't work strangely?

I am trying to post data to the sever to be save into mongodb. Notice get request is working right but I couldnt post any data to mongodb database.
The main code:
// Tools to be used in the web development
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
app.use(bodyParser.json());
Genre = require('./models/genre.js');
Book = require('./models/book.js');
let conn = mongoose.connection;
conn.openUri('mongodb://localhost/bookstore');
conn.on('error', err => console.error('mongodb connection error',
err));
conn.on('connected', () => console.info(`Connected to mongodb`));
conn.on('disconnected', () => console.info('Disconnected from
mongodb'));
// Routing to specific pages:
app.get('/', function(req, res){
res.send('Hello World');
});
app.get('/api/genres', function(req , res){
Genre.getGenres(function(err, genres){
if(err){
throw err;
}
res.json(genres);
})
});
app.post('/api/genres', function(req , res){
var genre = req.body;
Genre.addGenre(genre, function(err, genre){
if(err){
throw err;
}
res.json(genre);
})
});
app.get('/api/books', function(req , res){
Book.getBooks(function(err, books){
if(err){
throw err;
}
res.json(books);
})
});
app.get('/api/books/:_id', function(req , res){
Book.getBookById(req.params._id, function(err, book){
if(err){
throw err;
}
res.json(book);
})
});
//Specify the listening port
app.listen(3666);
//Display the url on the termianl
console.log('Server Running On http://localhost:3666');
Genres
var mongoose = require('mongoose');
var genreSchema = mongoose.Schema({
name:{
type: String,
requires: true
},
create_date:{
type: Date,
default: Date.now
}
});
var Genre = module.exports = mongoose.model('Genre', genreSchema);
module.exports.getGenres = function(callback, limit){
Genre.find(callback).limit(limit);
}
//add genre
module.exports.addGenre = function(genre, callback){
Genre.create(callback);
}
I post using postman app and once I press post I receive nothing and nothing be added to the database
Postman Procedure
Postman Procedure
and The database before and after the post procedure remain the same
enter image description here
Try this instead:
module.exports.addGenre = function(genre, callback){
Genre.create(genre, callback); // genre is object to be added, { name: "Name" } for example
}

Validation failed nodejs required field

I am creating creating a bookstore demo app in Node.js. I have ran into a little situation with the POST request for creating a genre. I've setup so the name of the genre must be required if not don't insert it to the database. But when I use Postman to POST to the url localhost:3000/api/genres with the JSON
{
"name": "TEST"
}
It throws an error
{
"error": "Genre validation failed"
}
When I remove the required field in the genreSchema it works but the name of the genre doesn't appear. Here is my code
Code:
genre.js
var mongoose = require("mongoose");
// Create a schema for genre
var Schema = mongoose.Schema;
var genreSchema = Schema({
name:{
type: String,
required: true
},
create_date:{
type: Date,
default: Date.now
}
});
var Genre = module.exports = mongoose.model("Genre", genreSchema);
// Methods
// get genres
module.exports.getGenres = function(callback, limit) {
Genre.find(callback).limit(limit);
};
// add a new genre
// TODO: Not working in Postman ValidationError
module.exports.addGenre = function(genre, callback) {
Genre.create(genre, callback);
};
app.js
var express = require("express");
var app = express();
var bodyParser = require("body-parser");
var mongoose = require("mongoose");
var Genre = require('./models/genre');
var Book = require('./models/book');
// Connect to mongoose
mongoose.connect("mongodb://localhost/bookstore");
var db = mongoose.connection;
app.get("/", function(req, res){
res.json({ error: "Please use /api/books or /api/genres" });
});
// GET /api/genres
app.get('/api/genres', function(req, res){
Genre.getGenres(function(err, genres){
if(err) {
res.json({error: err.message})
}
res.json(genres);
});
});
app.post('/api/genres', function(req, res){
var genre = req.body;
Genre.addGenre(genre, function(err, genre){
if(err) {
res.json({
error: err.message
})
}
res.json(genre);
});
});
// GET /api/books
app.get('/api/books', function(req, res){
Book.getBooks(function(err, books){
if(err) {
res.json({error: err.stack})
}
res.json(books);
});
});
// GET /api/book/:id
app.get('/api/book/:_id', function(req, res){
Book.getBookById(req.params._id, function(err, book){
if(err) {
res.json({error: err.message})
}
res.json(book);
});
});
app.listen(3000, function(){
console.log("Running on port 3000!")
});
Have you tried console.log(req.body); inside your post route? I don't think you've setup body-parser as middleware so req.body is coming in empty and therefore not sending anything to your Genre.addGenre method.

Resources