I am trying to insert a new record by express and node js using mongoose.
My config is my app.js:
import express from 'express';
import morgan from 'morgan';
import cors from 'cors';
import path from 'path';
const app = express();
// Conexión base de datos
const mongoose = require('mongoose');
const uri = 'mongodb://localhost:27017/marcosgarciatfg';
const options = {useNewUrlParser: true, useCreateIndex: true};
// Or using promises
mongoose.connect(uri, options).then(
/** ready to use. The `mongoose.connect()` promise resolves to mongoose instance. */
() => {
console.log('Conectado a DB');
},
/** handle initial connection error */
err => {
console.log(err);
}
);
app.use('/api', require('./routes/nota.js'));
//Middleware
app.use(morgan('tiny'));
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
//app.use(express.static(path.join(__dirname, 'public')));rs
// Rutas
app.get('/', (req, res) => {
res.send('Hello Wooooorld!');
});
And this my nota.js on routes:
import express from 'express';
const router = express.Router();
// importar el modelo nota
import Nota from '../models/nota';
// Agregar una nota
router.post('/nueva-nota', async(req, res) => {
const body = req.body;
try {
console.log('body: ' + body);
const notaDB = await Nota.create(body);
res.status(200).json(notaDB);
} catch (error) {
return res.status(500).json({
mensaje: 'Ocurrio un error',
error
});
}
});
This returns always 200:OK on Postman with empty response and in the console log the body is always undefined. What do I do wrong?
You need to apply express.json() middleware before using routes.
//Middleware
app.use(morgan('tiny'));
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use('/api', require('./routes/nota.js'));
Related
I'm using node and express and I'm trying to upload some files and some information with a form. The issue is that when I try to acces to anything in the form from backend it is undefined or empty. When I use req.body it's empty and when I try to use req.files they are undefined so I don't know what to do. This is the code:
routerProgress.post("/home/upload-progress", (req, res) => {
const user_id = req.user.id;
console.log(req.body);
const weight = req.body.weight;
const front = req.files.front;
const from_side = req.files.from_side;
const backwards = req.files.backwards;
let front_id = `${v4()}-${front.file.name}`;
let from_side_id = `${v4()}-${from_side.file.name}`;
let backwards_id = `${v4()}-${backwards.file.name}`;
const date = dateFormat(result.request_date, "yyyy-mm-dd");
from.mv('../../uploads/images', front_id, (req, res) => {
if (err) console.log(err);
else console.log("File Uploaded");
})
from_side.mv('../../uploads/images', from_side_id, (req, res) => {
if (err) console.log(err);
else console.log("File Uploaded");
})
backwards.mv('../../uploads/images', backwards_id, (req, res) => {
if (err) console.log(err);
else console.log("File Uploaded");
})
const newProgress = new Progress ({
user_id,
weight,
front_id,
from_side_id,
backwards_id,
date
})
res.redirect("/home");
});
The console.log is only {} and req.files.name_defined_in_form are undefined.
Here is my app.js
import express from 'express';
const app = express();
import path from 'path';
import sequelize from './db/db.js';
import { fileURLToPath } from 'url';
import flash from 'connect-flash';
import session from 'express-session';
import passport from 'passport';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// SERVER CONFIGURATION
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Listening at ${PORT}`);
sequelize.sync({ force: false })
.then(() => console.log('Database Connected!'))
.catch(err => console.log(err));
});
// VIEW SETTINGS
app.use(express.static(__dirname + "/public"));
app.set("view engine", "pug");
// app.engine('html', require('ejs').renderFile);
app.set('views', path.join(__dirname, "/public/views"));
// BODYPARSER
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
// EXPRESS SESSION
app.use(session({
secret: 'GymApp',
resave: true,
saveUninitialized: true
}));
// CONNECT FLASH
app.use(flash());
// PASSPORT MIDDLEWARE
import passportConfig from './config/passport.js';
passportConfig(passport);
app.use(passport.initialize());
app.use(passport.session());
// GLOBAL VAR
app.use((req, res, next) => {
res.locals.success_msg = req.flash('success_msg');
res.locals.error_msg = req.flash('error_msg');
res.locals.error = req.flash('error');
next();
});
// ROUTES
import { routerIndex } from './routes/index.js';
import { routerProgress } from './routes/app/progress.js';
import { routerAuthentication } from './routes/authentication.js';
import { routerHome } from './routes/app/home.js'
app.use(routerIndex);
app.use(routerProgress);
app.use(routerAuthentication);
app.use(routerHome);
And here is the form done with pug:
form(class="form add-form space-down" method="POST" enctype="multipart/form-data")
div.title
h1 UPLOAD NEW PROGRESS
div.form-group
label(for="weight") Weight:
input(type="number" name="weight" class="form-control" placeholder="Enter your weight")
div.form-group
label(for="front") Upload a front photo
input(type="file" name="front")
div.form-group
label(for="from_side") Upload a from side photo
input(type="file" name="from_side")
div.form-group
label(for="backwards") Upload a backwards photo
input(type="file" name="backwards")
div.button-container
button(type="submit" class="btn btn-primary btn-color space") Upload
If anyone know what I should do to solve this issue I would be very grateful with him.
In order to access the req.files object, you need to add a specific middleware named express-fileupload that allows this functionality.
Simply run npm i express-fileupload, and then add it to your app.js, like so:
const fileUpload = require('express-fileupload');
app.use(fileUpload());
In your specific app.js, you could add it near your other middleware, such as:
import express from 'express';
const app = express();
import path from 'path';
import sequelize from './db/db.js';
import { fileURLToPath } from 'url';
import flash from 'connect-flash';
import session from 'express-session';
import passport from 'passport';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// SERVER CONFIGURATION
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Listening at ${PORT}`);
sequelize.sync({ force: false })
.then(() => console.log('Database Connected!'))
.catch(err => console.log(err));
});
// FILE UPLOAD
const fileUpload = require('express-fileupload');
app.use(fileUpload());
// VIEW SETTINGS
app.use(express.static(__dirname + "/public"));
app.set("view engine", "pug");
// app.engine('html', require('ejs').renderFile);
app.set('views', path.join(__dirname, "/public/views"));
// BODYPARSER
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
// EXPRESS SESSION
app.use(session({
secret: 'GymApp',
resave: true,
saveUninitialized: true
}));
// CONNECT FLASH
app.use(flash());
// PASSPORT MIDDLEWARE
import passportConfig from './config/passport.js';
passportConfig(passport);
app.use(passport.initialize());
app.use(passport.session());
// GLOBAL VAR
app.use((req, res, next) => {
res.locals.success_msg = req.flash('success_msg');
res.locals.error_msg = req.flash('error_msg');
res.locals.error = req.flash('error');
next();
});
// ROUTES
import { routerIndex } from './routes/index.js';
import { routerProgress } from './routes/app/progress.js';
import { routerAuthentication } from './routes/authentication.js';
import { routerHome } from './routes/app/home.js'
app.use(routerIndex);
app.use(routerProgress);
app.use(routerAuthentication);
app.use(routerHome);
After installing and implementing the middleware via app.use(), the req.files object should now be accessible, given you are passing the files from your form properly.
I created a route and controller for my sign up.
Here's my route:
const express = require("express");
const router = express.Router();
const { signup } = require("../../controllers/auth");
router.post("/signup", signup);
module.exports = router;
And here's my controller:
exports.signup = () => (req, res) => {
const { name, email, password } = req.body;
res.json({
user: { name, email, password },
});
};
Inside my server.js file I register both:
const express = require("express");
const morgan = require("morgan");
const cookieParser = require("cookie-parser");
const cors = require("cors");
const mongoose = require("mongoose");
require("dotenv").config();
// routes
const blogRoutes = require("./routes/blog");
const authRoutes = require("./routes/auth");
// app
const app = express();
// db
mongoose
.connect(process.env.DATABASE, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => console.log("DB connected!"));
// middlewares
app.use(morgan("dev"));
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(cookieParser());
// cors
if (process.env.NODE_ENV == "development") {
app.use(cors({ origin: `${process.env.CLIENT_URL}` }));
}
// routes middleware
app.use("/api", blogRoutes);
app.use("/api", authRoutes);
// port
const port = process.env.PORT || 8000;
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
Now on my POSTMAN, I tried to put the data using POST http://localhost:8000/api/signup with the header and raw setup right.
{
"name": "SyRyan",
"email": "syryan#gmail.com",
"password": "brace1010"
}
The database is connected but the postman takes forever to load the json request back. Am I making any mistakes here? Please help!
I think that the problem is that signup is a function that returns a function, but it should be just a function that receives req & res as parameters:
exports.signup = (req, res) => {
const { name, email, password } = req.body;
res.json({
user: { name, email, password },
});
};
I am following the brad Traversy Nodejs Tutorial my server is connected and started also my Mongodb connection is running but localhost keep loading and not responding.
I have checked my URL for mongo connection also the password and username all are correct. I have also allow network access from all sources.
This was perfectly working before but now this keeps loading and loading
my db.js
const mongoose = require("mongoose")
const connectDB = async () => {
try {
const conn = await mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useFindAndModify: false,
useUnifiedTopology: true
})
console.log(`MongoDB connected ${conn.connection.host}`)
} catch (err) {
console.error(err)
process.exit(1)
}
}
module.exports = connectDB
my app.js
const express = require("express")
const path = require("path")
const dotenv = require('dotenv')
const morgan = require('morgan')
const exphbs = require('express-handlebars')
const passport = require('passport')
const connectDB = require('./config/db')
const routes = require('./routes/index')
const session = require("express-session")
const MongoDBStore = require('connect-mongodb-session')(session);
const mongoose = require('mongoose')
const methodOverride = require('method-override')
//locad config
dotenv.config({ path: './config/config.env' })
connectDB()
//passport config
require('./config/passport')(passport)
const app = express()
const PORT = process.env.PORT || 5000
//body parser
app.use(express.urlencoded({ extended: false }))
app.use(express.json())
//method override
// Method override
app.use(
methodOverride(function (req, res) {
if (req.body && typeof req.body === 'object' && '_method' in req.body) {
// look in urlencoded POST bodies and delete it
let method = req.body._method
delete req.body._method
return method
}
})
)
//logging
if (process.env.NODE_ENV === 'development') {
app.use(morgan('dev'))
}
//handlebars helpers
const { formatDate, truncate, stripTags, select } = require('./helpers/hbs')
//Hnadlebars
app.engine('.hbs', exphbs({ helpers: { formatDate, truncate, stripTags, select }, defaultLayout: 'main', extname: '.hbs' }));
app.set('view engine', '.hbs');
//sessions
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUnitialized: false,
store: new MongoDBStore({
mongooseConnection: mongoose.connection
})
//cookie: { secure: true }
}))
//set passport middleware
app.use(passport.initialize())
app.use(passport.session())
//set global variable
app.use(function (req, res, next) {
res.locals.user = req.user || null
})
//static folder
app.use('/', express.static(path.join(__dirname, 'public')))
//Routes
app.use('/', routes);
app.use('/auth', require('./routes/auth'));
app.use('/stories', require('./routes/stories'));
//listen
app.listen(PORT, console.log(
`server is running in ${process.env.NODE_ENV} mode on port ${PORT}`
))
my ./routes/index.js
const express = require('express')
const router = express.Router()
const { ensureAuth, ensureGuest } = require('../middleware/auth')
const Story = require('../models/story')
//#desc Login/Landing Page
//#route GET/
router.get('/', ensureGuest, (req, res, next) => {
res.render("login", {
layout: "login"
})
})
//#desc Login/Landing Page
//#route GET/
router.get('/dashboard', ensureAuth, async (req, res, next) => {
console.log(req.user)
try {
const stories = await Story.find({ user: req.user._id }).lean() //plain Js object
res.render("dashboard", {
name: req.user.firstName,
stories
})
} catch (error) {
console.log('Stories error', error)
res.render('error/500')
}
})
module.exports = router
my browser
I have found if you're using middlewares then must call next function at the end this was the reason my page wasn't loading
The error was at //set global variable middleware
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);
I am using express-validator package to validate requested data.
According to these answer I also did change the order or package declaration and initialization
below is my server.js file
const express = require("express");
const session = require("express-session");
const mongoose = require('mongoose');
const MongoStore = require('connect-mongo')(session);
const path = require('path');
const cookieParser = require("cookie-parser");
const bodyParser = require("body-parser");
const passport = require('passport');
const promisify = require('es6-promisify');
const expressValidator = require('express-validator');
const expressJwt = require("express-jwt");
const error_staus = 404;
const morgan = require('morgan');
const logger = require('./helper/logger');
const routes = require('./routes/index');
let server = "";
const bugsnag = require('bugsnag');
// import our configurations from config/tester.js file
const config = require("./config/tester").get(process.env.NODE_ENV);
require('./helper/passport');
require("./helper/translator");
// create our Express app
const app = express();
// view engine setup
app.set("views", `${__dirname}/views`);
app.set("view engine", "ejs");
// serves up static files from the public folder. Anything in app/ will just be served up as the file it is
app.use(express.static(path.join(__dirname, 'app')));
// Takes the raw requests and turns them into usable properties on req.body
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// Exposes a bunch of methods for validating data. Used heavily on userController.validateRegister
app.use(expressValidator());
// Sessions allow us to store data on visitors from request to request
app.use(session({
secret: '123456',
key: '99785',
resave: false,
saveUninitialized: false,
store: new MongoStore({ mongooseConnection: mongoose.connection })
}));
app.use(session({
"secret": 'secret12345',
"resave": false,
"saveUninitialized": true
}));
// Passport JS is what we use to handle our logins
app.use(passport.initialize());
app.use(passport.session());
// promisify some callback based APIs
app.use((req, res, next) => {
req.login = promisify(req.login, req);
next();
});
// begin logger
app.use(morgan('dev', {
skip: function (req, res) {
return res.statusCode < 400
}, stream: process.stderr
}));
app.use(morgan('dev', {
skip: function (req, res) {
return res.statusCode >= 400
}, stream: process.stdout
}));
app.use('/', routes);
app.use(function(req, res, next){
logger.error('404 page requested');
res.sendStatus(error_staus);
});
// done! we export it so we can start the site in start.js
module.exports = app;
This is the userController.js
const mongoose = require('mongoose');
const User = mongoose.model('User');
const promisify = require('es6-promisify');
exports.loginForm = (req, res) => {
res.render('login', { title: 'Login' });
};
exports.registerForm = (req, res) => {
res.render('register', { title: 'Register' });
};
exports.validateRegister = (req, res, next) => {
req.sanitizeBody('name');
req.checkBody('name', 'You must supply a name!').notEmpty();
req.checkBody('email', 'That Email is not valid!').isEmail();
req.sanitizeBody('email').normalizeEmail({
gmail_remove_dots: false,
remove_extension: false,
gmail_remove_subaddress: false
});
req.checkBody('password', 'Password Cannot be Blank!').notEmpty();
req.checkBody('password-confirm', 'Confirmed Password cannot be blank!').notEmpty();
req.checkBody('password-confirm', 'Oops! Your passwords do not match').equals(req.body.password);
const errors = req.validationErrors();
if (errors) {
req.flash('error', errors.map(err => err.msg));
res.render('register', { title: 'Register', body: req.body, flashes: req.flash() });
return; // stop the fn from running
}
next(); // there were no errors!
};
Note : I am using express-validator version 3.1.2
When I check request object, in that object there is all methods of express-validator too.
But try to use that method I am getting req.checkBody is not a function error.
Can anybody help with these issue ?