POST route indicating 404 error (EXPRESS) - node.js

Getting a 404 error on my POST route, here is what I have done in my auth.js (routes) file:
const express = require('express');
const router = express.Router();
const connection = require('../../helpers/db.js');
const bodyParser = require("body-parser");
router.use(bodyParser.json());
router.use(bodyParser.urlencoded({
extended: true
}));
//create a new user
router.post('/signup', function (req, res) {
const insert = `INSERT INTO users ( email, password, name, lastname) values ('${req.body.email}', '${req.body.password}','${req.body.name}', '${req.body.lastname}' )`
connection.query(insert, function (err, result) {
if(err) {
console.log('mysql error', error);
res.status(500);
res.send(error);
} else {
console.log('a new user was added!');
res.send('Congrats, new user!');
}
})
});
module.exports = router;
Here is my app.js file:
const http = require("http");
const path = require("path");
const express = require("express");
const bodyParser = require("body-parser");
const morgan = require("morgan");
const app = express();
const authRouter = require("./routes/auth/auth");
// Configuring the app
app.use(morgan("dev"));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static(__dirname + "/public"));
app.use("/signup", authRouter);
//starting node server
const server = app.listen(process.env.PORT || 3001, function(err) {
if(err) throw err;
console.log("Listening on port " + server.address().port);
});
If I change my route into a GET, it works fine, but as soon as I do a POST route it would keep telling me on postman there is a 404 error, been trying many things but im now stuck! Im a beginner here :)

I think you added a prefix to your route so the route is /signup/signup
Try to change this
app.use("/signup", authRouter);
To this
app.use(authRouter);

Related

TypeError: Cannot read property 'passport' of undefined nodejs

I'm currently working on a register and login system with Express, Node, Mongoose and Passport.js and the register mostly works fine , but there's a big issue with the login system. For some reason in the method I've created passport cannot read "passport" of undefined, so something is coming up as undefined but I can't seem to figure it out.
I don't know why it's not working, any help please!!
this my code
app.js
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const cors = require('cors');
const passport = require('passport');
const mongoose = require('mongoose');
const config = require('./config/database');
mongoose.connect(config.database);
mongoose.connection.on('connected', () => {
console.log('Connected to database ' + config.database);
});
mongoose.connection.on('error', (err) => {
console.log('Database error:' + err);
});
const app = express();
const users = require('./routes/users');
const port = 3000;
app.use(cors());
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json());
app.use(passport.initialize());
app.use(passport.session());
app.use('/users', users);
app.get('/', (req, res) => {
res.send('Invalid Endpoint');
});
app.listen(port, () =>{
console.log('Server started on port' + port);
});
users.js
const express = require('express');
const router = express.Router();
const passport = require('passport');
const jwt = require('jsonwebtoken');
const User = require('../models/user');
router.post('/register', (req, res, next) =>{
let newUser = new User({
name: req.body.name,
email: req.body.email,
username: req.body.username,
password: req.body.password
});
User.addUser(newUser, (err, user) => {
if(err){
res.json({success: false, msg:'Failed to register user'});
}else {
res.json({success: true , msg:'User registered'});
}
});
});
router.post('/authenticate', (req, res, next) =>{
res.send('AUTHENTICATE');
});
router.get('/profile', (req, res, next) =>{
res.send('PROFILE');
});
module.exports = router;
Your issue is with passport session. You need to use express session (remember to install in your dependencies) before it for it to work properly.
Your app.js should look like this:
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const cors = require('cors');
const passport = require('passport');
const mongoose = require('mongoose');
const config = require('./config/database');
const session = require("express-session");
mongoose.connect(config.database);
mongoose.connection.on('connected', () => {
console.log('Connected to database ' + config.database);
});
mongoose.connection.on('error', (err) => {
console.log('Database error:' + err);
});
const app = express();
const users = require('./routes/users');
const port = 3000;
app.use(cors());
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json());
app.use(session({secret: "secret"});
app.use(passport.initialize());
app.use(passport.session());
app.use('/users', users);
app.get('/', (req, res) => {
res.send('Invalid Endpoint');
});
app.listen(port, () =>{
console.log('Server started on port' + port);
});
Also, keep in mind that body parser is deprecated for Express 4.16.0 or higher. It has been re-added in methods express.json() and express.urlencoded() so if your Express version falls into that category, you can change your app.js to:
const express = require('express');
const path = require('path');
const cors = require('cors');
const passport = require('passport');
const mongoose = require('mongoose');
const config = require('./config/database');
const session = require("express-session");
mongoose.connect(config.database);
mongoose.connection.on('connected', () => {
console.log('Connected to database ' + config.database);
});
mongoose.connection.on('error', (err) => {
console.log('Database error:' + err);
});
const app = express();
const users = require('./routes/users');
const port = 3000;
app.use(cors());
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(session({secret: "secret"});
app.use(passport.initialize());
app.use(passport.session());
app.use('/users', users);
app.get('/', (req, res) => {
res.send('Invalid Endpoint');
});
app.listen(port, () =>{
console.log('Server started on port' + port);
});
I suggest adding comments to your code to keep it neat as well.
In case anyone else runs into this error:
express-session deprecated undefined resave option; provide resave option
express-session deprecated undefined saveUninitialized option; provide saveUninitialized option app.
In addition to #raijin30 answer, I had to add the properties below (:
resave: true,
saveUninitialized: true
Explanation as to why, can be found at: Node JS session error: express-session deprecated.
Had the same problem and noticed that passport got updated on Septmeber 23rd. So, I decided to install the previous version via npm using
npm install --save passport#0.4.1
This solved the issue for me. Not really sure how or why it happened in the first place, but it might help you.

how can we create subdomain dynamically using vhost . I have to share some data in username.domain.com and subdomain created only after user signup

I am trying with express vhost but i dont know how to create dynamically that means if a user signup with that username create a subdomain like username.domain.com
my app.js
const express = require("express");
const app = express();
const morgan = require("morgan");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const cors = require("cors");
var cookieParser = require("cookie-parser");
require("dotenv").config({ path: __dirname + "/.env" });
const vhost = require("vhost");
const subdomain = express();
const domain = "localhost";
app.use(vhost(`username.${domain}`, subdomain));
app.use(cookieParser());
subdomain.use(cookieParser());
app.use(morgan("dev"));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
subdomain.use(morgan("dev"));
subdomain.use(bodyParser.urlencoded({ extended: false }));
subdomain.use(bodyParser.json());
const userRoutes = require("./api/routes/user");
subdomain.use(userRoutes);
app.use("*", (req, res, next) => {
const error = new Error("Not found");
error.status = 404;
next(error);
});
app.use("*", (error, req, res, next) => {
res.status(error.status || 500);
res.json({
error: {
message: error.message,
},
});
});
module.exports = app;
Here i create subdomain manualy like http://username.localhost:3000/user
I want to create it dynamicaly after user signup using an API

Node js Express Error: ERR_TOO_MANY_REDIRECTS

Everything worked just fine until all of a sudden this error occurred: ERR_TOO_MANY_REDIRECTS. I had no luck in figuring it out on my own so please help me if you can.
I use express-handlebars and express to route my pages and I thing I saw where the problem occurres. In my bookController file when I use res.render('something') no matter from what route it always redirects me to '/' and when I use res.send('something') It redirects to where it defined.
This is my app.js file:
const express = require("express");
const mongoose = require("mongoose");
const passport = require("passport");
const path = require("path");
const bodyParser = require("body-parser");
const hbs = require("express-handlebars");
const cookieParser = require("cookie-parser");
const session = require("express-session");
const MongoStore = require("connect-mongo")(session);
const flash = require("connect-flash");
const routes = require("./routes/index");
const expressValidator = require("express-validator");
const errorHandlers = require("./handlers/errorHandlers");
const app = express();
const webpack = require("webpack");
const webpackConfig = require("./webpack.config.js");
const compiler = webpack(webpackConfig);
const webpackDevMiddleware = require("webpack-dev-middleware")(
compiler,
webpackConfig.devServer
);
app.use(webpackDevMiddleware);
app.use(require("webpack-hot-middleware")(compiler));
app.use(express.static(path.join(__dirname, "public")));
app.engine(
"hbs",
hbs({
extname: "hbs",
defaultLayout: "main",
layoutsDir: __dirname + "/views/layouts",
partialsDir: __dirname + "/views/partials"
})
);
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "hbs");
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(flash());
app.use(
session({
resave: false,
saveUninitialized: false,
secret: process.env.SECRET
})
);
app.use(cookieParser());
app.use(expressValidator());
app.use((req, res, next) => {
res.locals.flashes = req.flash();
next();
});
app.use("/", routes);
app.use(errorHandlers.flashValidationErrors);
module.exports = app;
This is my index.js file
const router = require("express").Router();
const bookController = require("../controllers/bookController");
const { catchErrors } = require("../handlers/errorHandlers");
router.get("/", bookController.home);
router.post("/contact", catchErrors(bookController.contactForm));
router.post("/productPage", catchErrors(bookController.productForm));
module.exports = router;
This is my bookController file:
const mail = require("../handlers/mail");
exports.home = async (req, res) => {
res.render("index");
};
exports.contactForm = async (req, res) => {
const email = req.body.email;
const subject = req.body.subject;
const text = req.body.text;
await mail.send({ email, subject, text });
res.redirect("/");
};
exports.productForm = async (req, res) => {
console.log(req.body);
res.redirect("/");
};
I will very appreciate any help.
Thank you.
Answer which solved the question.
If res.render() does not stop the request (Same way as res.send(html)), usually means there is error in the render function. As the behaviour of res.render() is that if it errors, it will trigger next(err).
https://expressjs.com/en/api.html#res.render
When an error occurs, the method invokes next(err) internally.
Errors are quite simple to be tracked in the function, by passing an callback into the render;
res.render('index', function(err, html) {
if (err) console.error(err);
res.send(html);
});
Once you can trace the error and fix it, problem should be solved.

Express and Vue. With axios, req.body is not working

Like i said in title. req.body don't work. I saw some examples and that use req.body(body-parser) well. But in my code, req.body is keep undefined. Also i found same problems and they said "app.use(bodyParser.json())" will work. But for me, no. So i ask how can i solve this error. Plz, help me.
This code is simple, Express and Vue login, signin test project. I think problem is in server file.
Server
var express = require("express");
var bodyParser = require("body-parser");
var path = require("path");
const mongoose = require("mongoose");
var index = require("./routes/index.js");
var login = require("./routes/login.js");
var signin = require("./routes/signin.js");
var app = express();
var http = require("http").Server(app);
mongoose.connect("mongodb://localhost:27017/test");
app.use('/', index);
app.use('/api/login', login);
app.use('/api/signin', signin);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.set("port", process.env.PORT || 3000);
app.use(express.static(path.join(__dirname, 'public')));
http.listen(app.get("port"), function() {
console.log("server start in " + app.get("port"));
})
Router
const express = require("express");
const router = express.Router();
const User = require("../models/user.js");
router.post("/", function(req, res, next) {
const id = req.body.id;
const password = req.body.password;
let info = {
error: "false",
words: "",
id: "",
password: ""
}
User.findOne({ id: id }, function(err, user) {
if(err) {
info.error = "true";
info.words = "Unknown Error Come Out.";
return res.send(info);
}
if(!user) {
info.error = "true";
info.words = "Please Check Your ID or Password";
return res.send(info);
}
info.id = id;
info.password = password;
console.log(info);
return res.send(info);
})
});
module.exports = router;
This body can not be resolved because of your middleware declaration order. You can check from the following blog about middleware execution sequence. Basically it equals to middleware declaration order.
https://derickbailey.com/2016/05/09/in-what-order-does-my-express-js-middleware-execute/
Declare bodyParser middleware before router middleware can solve your problem
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/api/login', login);

Request body undefined in supertest

I am testing an express API with supertest. I am trying to pass in body parameters into the test, as can be seen in the code snippets below, but it appears that the body parameters don't get passed in correctly since I get an error message that the body parameters are undefined.
Running the test with command mocha --recursive returns the following error:
Cannot read property 'email' of undefined
Below is the code from file email-suite.js referencing supertest
'use strict';
var express = require("express");
var bodyParser = require('body-parser');
var mongoose = require("mongoose");
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
var supertest = require("supertest");
var chai = require("chai");
var should = chai.should();
var api = require("../server.js");
describe("Email Module", function() {
this.timeout(25000);
before(function(done){
mongoose.createConnection(/* connectionstring */);
mongoose.connection.on('open', function(err) {
if(err) console.log(err);
console.log('connected to server');
});
done();
});
it("Check Email Count", function(done) {
var body = { email: "email#email.com" };
supertest(api)
.post("/emailCount")
.set('Accept', 'application/json')
.send(body) // body is undefined
.expect(200)
.expect('Content-Type', /json/)
.end(function(err, res) {
if(err) return done(err);
res.body.count.should.equal(2);
done();
});
});
});
Below is the code from file email-api.js
'use strict';
var express = require("express");
var bodyParser = require('body-parser');
var router = express.Router();
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
router.post('/emailCount', function(req, res) {
var email = req.body.email; // req.body is undefined
}
module.exports = router;
Below is the code from the file server.js
var express = require("express");
var app = express();
app.set("port", process.env.PORT || 3000);
var router = require("./user/email-api");
app.use('/', router);
app.listen(app.get("port"), function() {
console.log("App started on port " + app.get("port"));
});
module.exports = app;
Put body-parser always after express object and before every routes in main server file like this
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
//Router task start from here
Other wise always will get undefined since router call first and body parsed later.
Thank you abdulbarik for your answer. I want to add some extra information to aid clarity in case people are still getting undefined values for the request body object, and if (as in my case) your routers and tests are setup differently.
Here is the router that we shall test:
// router.js
const express = require("express");
const router = express.Router();
router.post("/", (req, res) => {
res.json({ success: true, data: req.body });
});
module.exports = router;
The following test code will result in the request body being undefined, and thus the test failing:
// router.test.js
const express = require("express");
const request = require("supertest");
const bodyParser = require("body-parser");
// set up the test app - this will fail
const app = express();
app.use("/routerPath", require("./router")); // this will cause the test to fail, as the router should be setup after the body-paser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// run the test
it("successful response", async () => {
const response = await request(app)
.post("/routerPath")
.send({
firstname: "John",
lastname: "Smith",
})
.set("Accept", "application/json");
expect(response.status).toEqual(200);
expect(response.body).toEqual({
success: true,
data: {
firstname: "John",
lastname: "Smith",
},
});
});
The reason why, as explained by abdulbarik, is that the body-parser code should always be before the router code, so that the parser runs before the router. To make the test pass, simply swap these lines around:
// set up the test app - this will work now
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use("/routerPath", require("./router")); // the router setup should happen after the body-parse setup
I hope that is a helpful clarification.

Resources