NodeJS posts.findOne(... Is returning 404 not found

775 views Asked by At

I am putting together a blog from NodeJs, Pug, Express, Monk, etc and having trouble retrieving a single post from the db. I keep getting a 404 not found error. I am not sure what I am doing wrong but if you can scan my code and see if I am missing something, I would sure appreciate it.

posts.js

var express = require("express");
var router = express.Router();
var multer = require("multer");
var upload = multer({ dest: "./public/images" });
var mongo = require("mongodb");
var db = require("monk")("localhost/nodeblog");

router.get("/show/:id", function (req, res, next) {
  var posts = db.get("posts");

  posts.findOne({ '_id': req.params.id }, function (err, post) {
    res.render("show", {
      'post': post
    });
  });
});

app.js

var express = require("express");
var path = require("path");
var favicon = require("serve-favicon");
var logger = require("morgan");
var cookieParser = require("cookie-parser");
var bodyParser = require("body-parser");
var session = require("express-session");
var multer = require("multer");
var upload = multer({ dest: "./public/images" });
var expressValidator = require("express-validator");

var mongo = require("mongodb");
var db = require("monk")("localhost/nodeblog");

var routes = require("./routes/index");
var posts = require("./routes/posts");
var categories = require("./routes/categories");

var app = express();

app.locals.moment = require("moment");

app.locals.truncateText = function(text, length) {
  var truncatedText = text.substring(0, length);
  return truncatedText;
};

// view engine setup
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "pug");

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger("dev"));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, "public")));

// Express Session
app.use(
  session({
    secret: "secret",
    saveUninitialized: true,
    resave: true
  })
);

// Express Validator
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
      };
    }
  })
);

// Connect-Flash
app.use(require("connect-flash")());
app.use(function(req, res, next) {
  res.locals.messages = require("express-messages")(req, res);
  next();
});

// Make our db accessible to our router
app.use(function(req, res, next) {
  req.db = db;
  next();
});

app.use("/", routes);
app.use("/posts", posts);
app.use("/categories", categories);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error("Not Found");
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get("env") === "development") {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render("error", {
      message: err.message,
      error: err
    });
  });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render("error", {
    message: err.message,
    error: {}
  });
});

module.exports = app;

categories.js index.js and posts.js are all inside the routes folder. Inside the views folder, I have addcategory.pug, addpost.pug, error.pug, index.pug, layout.pug and show.pug If you need to see any of those, please let me know and I will edit this query. Thank you.

index.js

var express = require("express");
var router = express.Router();
var mongo = require("mongodb");
var db = require("monk")("localhost/nodeblog");

/* GET home page. */
router.get("/", function(req, res, next) {
  var db = req.db;
  var posts = db.get("posts");
  posts.find({}, {}, function(err, posts) {
    res.render("index", { posts: posts });
  });
});

module.exports = router;

categories.js

var express = require("express");
var router = express.Router();
var mongo = require("mongodb");
var db = require("monk")("localhost/nodeblog");

router.get("/show/:category", function(req, res, next) {
  var posts = db.get("posts");

  posts.find({ category: req.params.category }, {}, function(err, posts) {
    res.render("index", {
      title: req.params.category,
      posts: posts
    });
  });
});

router.get("/add", function(req, res, next) {
  res.render("addcategory", {
    title: "Add Category"
  });
});

router.post("/add", function(req, res, next) {
  // Get Form Values
  var name = req.body.name;

  // Form Validation
  req.checkBody("name", "Name field is required").notEmpty();

  // Check Errors
  var errors = req.validationErrors();

  if (errors) {
    res.render("addpost", {
      errors: errors
    });
  } else {
    var categories = db.get("categories");
    categories.insert(
      {
        name: name
      },
      function(err, post) {
        if (err) {
          res.send(err);
        } else {
          req.flash("success", "Category Added");
          res.location("/");
          res.redirect("/");
        }
      }
    );
  }
});

module.exports = router;

show.pug

extends layout
block content
    .post
     h1=post.title
     p.meta Posted in 
      a.category-link(href='/categories/show/' + post.category) #{post.category} 
      | by #{post.author} on #{moment(post.date).format("MM-DD-YYYY")}
     img.main-image(src='/images/' + post.mainimage)
     !=post.body

Originally, I had

posts.findById(

but that did not work either.

Any help on this will be greatly appreciated. Thank you in advance.

3

There are 3 answers

12
RedJandal On

This code here is causing the issue.

app.use(function(req, res, next) {
  var err = new Error("Not Found");
  err.status = 404;
  next(err);
});

Effectively this code is middleware that changes the status of every request to 404.

2
mstrbrt On

you should pass the id paramater as an objectId by converting it using the mongoDB module

var ObjectId = require("mongodb").ObjectId;

router.get("/show/:id", function (req, res, next) {
  var posts = db.get("posts");

  posts.findOne({ '_id': new ObjectId(req.params.id }, function (err, post) {
    res.render("show", {
      'post': post
    });
  });
});```
3
Savan Padaliya On

I would suggest you to use findById as you are finding by id and use promise. in your case it would be like:

posts.findById({ '_id': req.params.id })
.then(post => {
  res.render(post)
})
.catch(error => {
  console.log(error)
})