I am trying to add a method
loadSiteSettings to express module
In app.js
var express = require('express');
var path = require('path');
var mongoose = require('mongoose');
//Set up default monggose connection for mongo db
var mongoDB = 'mongodb+srv://***:*****#cluste******j.mongodb.net/cms?retryWrites=true&w=majority';
mongoose.connect(mongoDB,{useNewUrlParser: true});
//Get the default connection
var db = mongoose.connection;
//Bind connection to error event (to get notification of connection errors)
db.on('error',console.error.bind(console, 'MongoDB connection error:'));///????????
var app = express();
///////////////////////////////////////////////////////////
var indexRouter = require('./routes/index');
app.loadSiteSettings = async function()
{
let setting = await db.collection('settings').findOne();
app.locals.siteSettings = setting;
}
app.loadSiteSettings();
//////////////////////////////////////////////////////
module.exports = app;
Index.Js for router
var express = require('express');
var router = express.Router();
var app = require('../app');
var util = require('util');
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index');
});
///////////////////////////////////////////
router.get('/reloadSettings', function(req,res,next){
app.loadSiteSettings();
})
///////////////////////////////////////
module.exports = router;
so problem lies here, when server start it calls app.loadSiteSettings() in app.js
but when i use route '/reloadSettings' it seems app is undefined in index.js
This is an issue with circular dependencies and module.exports. This answer shows the same problem.
What's happening is app.js is required first and starts processing. The important thing to understand is that a file pauses execution while requiring a new file.
So when app.js requires ./routes/index, it has not finished processing, and has not reached module.exports = app. This means that when your routes file requires app.js, it's requiring it in its current state, which is the default export {}.
Thankfully there's a very simple fix:
// can be imported and tested separately from the app
const loadSiteSettings = function() {
return db.collection('settings').findOne();
}
router.get('/reloadSettings', async function(req,res,next){
let settings = await loadSiteSettings();
req.app.locals.siteSettings = settings
res.send(200); // signal the response is successful
})
This explains the issue in a lot more depth in case you're interested
Related
I am trying to make post request but unable to get values in Postman; it's sending undefined. I am using Express version 4.17.1. Below is my code:
const express = require('express');
const router = express.Router();
const MongoClient = require('mongodb').MongoClient;
const dburl = process.env.URL;
router.use(express.json());
router.use(express.urlencoded({extended:true}));
router.post('/register',(req,res) => {
var data = {
name:req.body.name,
email:req.body.email,
};
res.send(data);
});
module.exports = router;
What am I doing wrong?
Your code snippet works, tested with express 4.17.1 on node 12.19.0. The issue must be from elsewhere.
Possible issues are:
The parser for router could have been overridden by the parser for app (assuming you're calling app.use(router) somewhere).
Can you move this to app level?
router.use(express.json());
router.use(express.urlencoded({extended:true}));
I am trying to run a simple node application using nide modules and testing it using the Advance Rest Client.
The console is not showing any error.
But I am not getting anything in the output.
While running this on ARC, I am getting : Cannot /GET data
Text version of the code:
MainFile:
var express = require('express');
//var morgan = require('morgan');
var bodyparser = require('body-parser');
var hostname = 'localhost';
var port = '3000';
var app = express();
//app.use(morgan('dev'));
var dishRouter = express.Router();
dishRouter.use(bodyparser.json());
var allDishes = require('./dishRouter');
//For all dishes
dishRouter.route('/dishes')
.get(allDishes.dishesGet)
.delete(allDishes.dishesDelete)
.post(allDishes.dishesPost)
;
//For specific dishesDelete
dishRouter.route('/dishes/:dishid')
.get(allDishes.dishSpecificGet)
.delete(allDishes.dishSpecificDelete)
.put(allDishes.dishSpecificPut)
;
app.listen(port,hostname,function(){
console.log('server runing properly');
});
dishRouter file:
console.log('in dishrouter file');
module.exports.dishesGet = function(req,res,next){
console.log('inside GET');
res.end('Will be displaying all the dishes');
};
module.exports.dishesDelete = function(req,res,next){
res.end('Will delete all the dishes');
};
module.exports.dishesPost = function(req,res,next){
res.end('will add the new dishes');
};
module.exports.dishSpecificGet = function(req,res,next){
res.end('displaying the specific dish :'+req.params.dishid);
};
module.exports.dishSpecificDelete = function(req,res,next){
res.end('Will delete the specific dish with id : '+req.params.dishid);
};
module.exports.dishSpecificPut = function(req,res,next){
res.write('will update the specific dish :'+req.params.dishid);
res.end('Updating the dish with values as name : '+req.body.name);
};
According to body-parser docs
Looks like your router is a bit broken here:
dishRouter.use(bodyParser.json())
Try switching this to:
app.use(bodyParser.json())
And I can recommend creating router in the file, where you write handlers and just export router.
UPDATE:
Here is what you forgot:
app.use(dishRouter)
When calling express.Router() you're just creating an instance of the router, but you have to connect it to the express application instance.
I have used the express generator plugin and I had all my routes generated on routes/index.js but I'm doing a refactor now and I'm putting all of the routes in it's respective router files. The thing is that the 'pg' module works fine if I put my code on the index.js :
index.js
var express = require('express');
var router = express.Router();
var pg = require('pg');
var connectionString = 'postgres://postgres:postgres#localhost:5432/dataDB';
router.use('/api/events', require('./events'))
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
module.exports = router;
Now if I request a route from the routes/events.js file I get a 'pg'(postgres driver) not defined
var express = require('express');
var router = express.Router();
var pg = require('pg');
var connectionString = 'postgres://postgres:postgres#localhost:5432/dataDB';
//get all events from a user
router.get('/user/id/:id_user', function(req, res) {
.....
});
router.post('/friends/', function(req, res) {
........
});
module.exports = router
And the app.js only includes the router/index.js file ......How can I solve this?. The requests are getting to the router/events.js file correctly, but it's just not recognizing the 'pg' module require......Thank you very much
The problem was that I was including
var pg = require('pg');
in both routes/index.js and in routes/events.js
I removed that line from the index.js and left it only in event.js and now it works perfectly. That require is going in the model layer anyway, but now that I fixed it I would like to know why requiring something on one script and then requiring something on another script fails on express given the fact that I included express and the router in both files and those 2 lines didn't fail but the mentioned line did......
I'm building a web app with Express and Node and am trying to factor my routing so that I don't have hundreds of routes in the same file. This site serves different files within the projects directory, so I made a file in routes/ called projectRoutes.jsto handle the routing for project files:
var express = require('express');
module.exports = function() {
var functions = {}
functions.routeProject = function(req, res) {
res.render('pages/projects/' + req.params.string, function(err, html) {
if (err) {
res.send("Sorry! Page not found!");
} else {
res.send(html);
}
});
};
return functions;
}
Then, in my routes.js, I have this...
var projectRoutes = require("./projectRoutes");
router.get('/projects/:string', function(req, res) {
projectRoutes().routeProject(req, res);
});
Is there a better way to structure this functionality within projectRoutes.js? In other words, how can I configure projectRoutes.js so that I can write the follow line of code in index.js:
router.get('/projects/:string', projectRoutes.routeProject);
The above seems like the normal way to handle something like this, but currently the above line throws an error in Node that says the function is undefined.
Thanks for your help!
You should use the native express router, it was made to solve this exact problem! It essentially lets you create simplified nested routes in a modular way.
For each of your resources, you should separate out your routes into several modules named <yourResource>.js. Those modules would contain all of the routing code as well as any other configuration or necessary functions. Then you would attach them in index.js with:
var apiRoute = router.route('/api')
apiRoute.use('/< yourResource >', yourResourceRouter)
For example, if you had a resource bikes:
In index.js:
var apiRoute = router.route('/api')
, bikeRoutes = require('./bikes')
apiRoute.use('/bikes', bikeRoutes)
Then in bike.js:
var express = require('express')
, router = express.Router()
, bikeRoutes = router.route('/')
bikeRoutes.get(function (req, res) {
res.send('api GET request received')
});
module.exports = bikeRoutes
From there its easy to see that you can build many different resources and continually nest them.
A larger of example of connecting the routes in index.js would be:
var apiRoute = router.route('/api')
, bikeRoutes = require('./bikes')
, carRoutes = require('./cars')
, skateboardRoutes = require('./skateboards')
, rollerskateRoutes = require('./rollerskates')
// routes
apiRoute.use('/bikes', bikeRoutes)
apiRoute.use('/cars', carRoutes)
apiRoute.use('/skateboards', skateboardRoutes)
apiRoute.use('/rollerskates', rollerskateRoutes)
Each router would contain code similar to bikes.js. With this example its easy to see using express's router modularizes and makes your code base more manageable.
Another option is to use the Router object itself, instead of the Route object.
In Index.js:
//Load Routes
BikeRoutes = require('./routes/Bike.js');
CarRoutes = require('./routes/Car.js');
//Routers
var express = require('express');
var ApiRouter = express.Router();
var BikeRouter = express.Router();
var CarRouter = express.Router();
//Express App
var app = express();
//App Routes
ApiRouter.get('/Api', function(req, res){...});
ApiRouter.use('/', BikeRouter);
ApiRouter.use('/', CarRouter);
In Bike.js:
var express = require('express');
var router = express.Router();
router.get('/Bikes', function(req, res){...});
module.exports = router;
Similarly in Car.js
I have the following files
lib/pub
lib/pub/index.js
app.js
On App.js
I have:
// app.js
var express = require("express")
, app = express()
, router = express.Router()
;
...
router.use('/pub',require('./pub'));
and then on index.js
// pub/index.js
var express = require('express')
, router = express.Router()
;
console.log("file loaded successfully")
module.exports = function(){
router.get('/',function(req,res){
console.log("got the get request")
})
}
The problem I have when I do localhost/pub request, I never get the got the get request, no matter whatever I try to change the code around, trying to add pub to the path.
router.get('/',...
router.get('/pub',...
router.get('./pub,...
router.get('./',...
router.get('pub',...
etc...
None of those or any other silly way I have attempted work... I can never get the log to say yes I got the request...
What am I doing wrong ! (expressjs changes so frequently and radically, any web tutorials become redundant or any previous help others got)
(edited to reflect comments)
If you want to move your routes to an external file, use the following pattern:
app.js
var express = require('express');
var app = express();
require('./routes')(app);
routes.js
module.exports = function(app) {
app.get('/pub', function(req, res) {
console.log('got the get!');
res.end();
});
};