I am new to Node.js and trying to make an API which would add a user into MongoDB database, my problem is I am Unable to access any properties of res & req in my controller. I tried searching for answer on SO but it seems the problem lies how you export the routes but the more I see the answers the more I get confused.
Here is part of my Server.js file,
const express = require("express");
const { readdirSync } = require("fs");
const dotenv = require("dotenv");
const app = express();
const mongoose = require("mongoose");
app.use(cors(options));
app.use(express.json());
This is how I am registering Routes,
readdirSync("./routes").map((r) => app.use("/", require("./routes/" + r))); //here route folder is being registered as a controller
Now in my Routes/User.js
const express = require("express");
const { register } = require("../controllers/user");
const router = express.Router();
router.get("/register", register);
module.exports = router;
In Controller/User.js
exports.register = async (req, res) => {
// here is the problem, when this controller is hit, i want to send response back
// like res.send("user added successfully") but I am unable to access req."send" or "body"
};
I have Tried using app.use(express.json()); answer on some forums but to no avail.
Related
Given a simple Express app
const express = require('express')
const app = express()
app.get('/users/:userId', (req, res) => {
console.log(req.orginalUrl) // /users/1
console.log(req.route.path) // /users/:userId
res.json({})
})
It gives me the right and complete route schema req.route.path.
But if we use a router to abstract the first part of the URI then it doesn't give the full route schema anymore.
const express = require('express')
const app = express()
const users = express.Router()
.get(':userId', (req, res) => {
console.log(req.orginalUrl) // /users/1
console.log(req.route.path) // /:userId
res.json({})
})
app.use('/users', users)
It there a way to get /users/:userId while using routers?
You just have to concatenate baseUrl and path like this :
let fullPath = req.baseUrl + req.route.path;
I have a node.js(express) app in which i have defined all my routes, controllers and all that.
customer.route.js
const express = require('express');
const Controller = require('../controllers/customer.controller');
const { customerValidationRules, validate } = require('../middlewares/request- validator.middleware');
const router = express.Router();
router.route('/create').post(customerValidationRules, validate, Controller.create);
module.exports = router;
my index.js file inside routes folder
const express = require('express');
const cors = require('cors');
const responseUtil = require('../helpers/response.helper');
const customerR = require('../routes/customer.route');
const router = express.Router();
router.use(cors());
router.use('/customers', customerR);
/** Returned when requested api url not found **/
router.use((req, res) => responseUtil.sendNotFound(res));
module.exports = router;
And my app.js(root file)
const routes = require('./routes');
const app = express();
app.use('/api/v1', routes);
Now when i am hitting my api via postman with this api url
http://localhost:3003/api/v1/customers/create
So it keeps going and none of my logs priting on the console it means that request is not coming to my server now. Can any one let me know what'st he issue in it.
Because routes in Express router are not chained.
If you have
app.use('/customers',customerRouter)
Then you have to in your customerRouter define the whole route:
router.post('/customers/create', yourPostStuff)
// app.js file
const express = require('express');
const morgan = require('morgan');
const courseRouter = require('./routers/courseRouter');
const app = express();
/// middleware
app.use(morgan('dev'));
app.use(express.json());
app.use((req,res,next)=>{
console.log('from middle ware');
next();
});
app.use((req,res,next)=>{
console.log('from second middle ware');
next();
});
/// routes
app.use('/courses',courseRouter);
module.exports = app;
//////////////// server.js file
const dotenv = require('dotenv');
const mongoose = require('mongoose');
const app = require('./app');
dotenv.config({path:"./config.env"});
mongoose.connect(process.env.DATABASE_LOCAL,{
useNewUrlParser:true,
useCreateIndex:true,
useFindAndModify:false,
useUnifiedTopology: true
}).then(con =>console.log(con.connections));
app.listen(3000,()=>{
console.log(` App running at port 3000`);
});
/////////////////courseRouter.js file
const express = require('express');
const courseController = require('./../controlers/courseController');
const router = express.Router();
router.
route('/courses').
get(courseController.getCourses);
module.exports = router;
//////// coursecontroller.js file
const Course = require('./../models/course.model');
exports.getCourses = async (req,res)=>{
try{
const courses = await Course.find({});
res.status(200).json({
status:'sucess',
data:{
courses
}
})
} catch (err){
console.log(err);
}
}
I'm trying to get simple get response from local mongoDB which is running at localhost:27017.
In there I have winrobot DB with collection courses which have one document.
So, my server is listening at port 3000, I have divided my routes , controllers and model according to MVC.
When I tried to get courses collection, I get "GET /courses 404 14.068 ms - 146" this morgan request log.but if I delete these controller and routes and implement that in app.js that works fine... so I want routes and controller in different files and still get courses collection.added the github repo of same code
You have this line:
app.use('/courses',courseRouter);
But then you are defining the router in the course file:
const router = express.Router();
router.
route('/courses').
get(courseController.getCourses);
Basically what ends up happening is you create a route that looks like:
/courses/courses/
You should change this:
router.
route('/').
get(courseController.getCourses);
Now your app will use the router you created properly.
My problem
I am trying to write a register/login page in node.js using express.js. I have decided to split routes and app initialization into two files. When I send a POST request to localhost:3000/register with the data {"username":"xyz","password":"xyz"}, the request object has the attribute body. However when I try to access this attribute, I get undefined.
My current code
// app.js
// Load express and define port
const express = require('express');
const app = express();
const port = 3000;
// App Configurations
app.use(express.json())
// Load Routes
var registerRouter = require('./controllers/register.js');
// Use Routes
app.use('/register', registerRouter);
// Start App
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
// controllers/register.js
// requires
var argon2i = require('argon2-ffi').argon2i;
var bodyParser = require('body-parser');
var {Database, Model} = require('mongorito');
var crypto = require('crypto')
var Promise = require('bluebird');
var randomBytes = Promise.promisify(crypto.randomBytes);
var express = require('express');
// define router
var router = express.Router();
// Mongo Connection
const db = new Database('localhost/test', {
reconnectTries: 5
});
// Models
class User extends Model {}
// Register Models
db.register(User);
// Routes
router.post('/', async (res, req) => {
console.log(req.body);
if(!req.body) return req.sendStatus(400);
const username = req.body.username;
const salt = randomBytes(32);
const password = argon2i.hash(req.body.password, salt);
var user = new User({
username: username,
password: password,
salt: salt
});
await user.save;
res.send("User Created");
});
// Disconnect From Database
db.disconnect;
//export router
module.exports = router;
My expected result
I expect to be able to access req.body and req.body.username.
You have a small issue in you code. The router.post callback function first parameter is req and the second is res. The Callback function parameters are fixed not named parameters.
You are trying to get the body on the response object, though the name of the parameter is req but it still holds the response object. which is causing the issue.
Please change it.
Wrong:
router.post('/', async (res, req) => {
Correct:
router.post('/', async (req, res) => {
I see you are importing bodyParser in controller/register but not setting it, at least in this snippet. if you do not have any special reasons for putting it in the controller, then do this instead.
// app.js
// Load express and define port
const express = require('express');
const bodyParser = require('body-parser'); // new code
const app = express();
app.use(bodyParser.urlencoded({ extended: true })); // new code
const port = 3000;
// App Configurations
app.use(express.json())
// Load Routes
var registerRouter = require('./controllers/register.js');
// Use Routes
app.use('/register', registerRouter);
// Start App
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
I'm doing to some refactoring in my application and I don't understand why this case is failing.
index.js
const express = require('express');
const router = express.Router();
const models = require('../models');
const listRoute = require('./list');
router.use('/list', listRoute);
list.js
const express = require('express');
const router = express.Router();
const models = require('../models');
const sendListDataToView = (req, res, view) => {
// get data from backend and pass to template
}
router.route('/list/show/:id')
.get((req, res) => {
sendListDataToView(req, res, 'view-list')
})
router.route('/list/expand-records-forms/:id')
.get((req, res) => {
sendListDataToView(req, res, 'edit-list-records')
})
module.exports = router;
Trying to navigate to /list/show/3 throws a 404 error. However, if I move the definitions of these routes and sendListDataToView to index.js, the page loads fine. Is this because of the multiple router.routes?
I'm just going to wipe my original answer.
You need to create the app.
const express = require('express');
const app = express();
const models = require('../models');
const listRoute = require('./list');
app.use('/list', listRoute); // Using express now.
app.listen(8080); // starts server