Module.Exports not working for Express - javascript

I'm trying to organize routes in express. But I'm having trouble getting a simple setup to work. I have two files, api.js, which has the routing info, and index.js, which runs the server.
However, when I try this, I get no response on localhost:3000.
api.js
var express = require('express');
module.exports = function() {
var router = express.Router();
router.get('/', function(req, res) {
res.send('im the home page!');
});
return router;
}
index.js
var express = require('express');
var app = express();
var router = require('./api');
app.use('/',router);
app.listen(3000);
console.log('Listening on port 3000!');
However, when I change api.js to this, it works:
api.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.send('im the home page!');
});
module.exports = router;
I don't understand why the bottom api.js works when the top one doesn't. Shouldn't module.exports return the same express Router in both cases?

The difference is that in the first version you're exporting a function that returns the router vs the second version where you're exporting the router itself.
In the first version, Express calls your exported function, passing it req and res, expecting it to somehow handle the request. The exported function of course is not designed to handle a request (it's just creating a router and returning it), so the request times out.

Related

app.set and then TypeError: app.get is not a function

While using express 4.x, I am setting the port in my server.js like in the following.
var express = require('express');
var app = express();
...
var port = process.env.PORT || 8080;
app.set('port', port);
...
module.exports = app;
But when I try to access it within my routes file, like the following...
// path to routes file is app/models, hence the '../../'
var app = require('../../server');
// default route
router.get('/', function (req, res) {
res.send('Hello! The API is at http://localhost:' + app.get('port') + '/api');
});
... I get the following error.
TypeError: app.get is not a function
What on earth is going on?
Okay, I have finally figured it out. The app was not properly being set within the routes file because we were previously doing module.exports = app after require('./app/models/routes'); within server.js. So as soon as I moved the exporting of the app to happen before the requiring of the routes file... everything worked!
I don't know exactly what's going on and I don't know if you would like this solution. I had a similar problem as this once.
in the main file i did something like
var express = require('express');
var app = express();
....
var routes = require("./routes/path")
routes(app);
and in routes i did something like
in where you have "./routes/path" file:
module.exports = function(app){
//I got access to app.locals
}
you see I passed along the express app .
basically routes is a function that takes app as a parameter.
I tried app.set("app", app) and I don't think that worked.
It looks like app is not being defined. you could also try something like this.
router.get('/', function (req, res) {
var app =req.app.get("app")
res.send('Hello! The API is at http://localhost:' + app.get("port") + '/api');
});
https://stackoverflow.com/a/15018006/1893672
In your route handling for GET, POST, etc, you should be receiving the 'req' dependency. App should be attached to this so just reference req.app:
router.get('/',function(req,res,next){
console.log(app.get('secret'));
}
No require statement should be necessary.

app.post is not a function express node

I had all my routes in server.js but I wanted to make it modular and put into a folder called routes. I created a file called apis.js in routes folder but as I did that I get TypeError: app.post is not a function
server.js:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var urlencode = bodyParser.urlencoded({ extended: true});
app.use(express.static('public'));
var apis = require('./routes/apis');
app.use('/', apis);
module.exports = app;
apis.js:
module.exports = function(app){
app.get('/', function(req, res) {
res.send('OK');
});
app.post('/idea', function(req, res) {
...
});
};
Also, having module.exports = app in server.js is important as I have tests running and I want a instance of app everytime.
What am I missing?
Better approach :-
server.js
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var urlencode = bodyParser.urlencoded({ extended: true});
app.use(express.static('public'));
var apis = require('./routes/apis');
app.use('/', apis);
module.exports = app;
apis.js :-
var router = require('express').Router();
router.post('/url',function(req,res,next){
//your code
})
module.exports = router
You need to pass in your express app into your apis module so it can attach the routes to your app. If you want to use app.use to put your routes in a different root path, you can create another express router, and attach your routes to that, then app.use that router:
server.js:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var urlencode = bodyParser.urlencoded({ extended: true});
app.use(express.static('public'));
var apis = express.Router();
require('./routes/apis')(apis);
app.use('/', apis);
module.exports = app;
There's a couple different methods for connecting your app to your routes, and it looks to me like you are mixing them together, resulting in your error.
The fix already mentioned...
var router = require('express').Router();
router.post('/url',function(req,res,next){
//your code
})
module.exports = router
...works with the way you currently have your server.js file set up.
Another method that doesn't require you to modify your apis.js file is to require it in server.js using
require("./routes/apis.js")(app);
instead of
var apis = require('./routes/apis');
app.use('/', apis);
This ensures that the variable app is passed into the function in apis.js
The first version is recommended, but hopefully this explains why you are getting confused between the two, i.e. because the second is an alternate version.
See Differences between express.Router and app.get? for more information on why the router version is recommended.

app.get returned undefined in Node/Express

I'm using express in my app.js I set something like this
var express = require('express');
var app = express();
app.set('myVar', 'hello');
then in my controller I want to get the value. I do
var express = require('express');
var app = express();
console.log(app.get('myVar')) // undefineded
Any idea why?
Your controller creates a new, fresh instance of Express. If you want to be able to share variables, you need to pass the instance from app.js to your controller:
// app.js
var express = require('express');
var app = express();
app.set('myVar', 'hello');
require('./controller')(app);
// controller.js
module.exports = function(app) {
console.log(app.get('myVar'));
};
EDIT: judging by the comments, the issue isn't so much passing app around, but moving parts of the application to separate modules. A common setup to enable that would look like this:
// app.js
var express = require('express');
var app = express();
app.set('myVar', 'hello');
app.use('/api', require('./controller/auth'));
// controller/auth.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
console.log(req.app.get('myVar'));
return res.send('hello world');
});
module.exports = router;
In your example you are instantiating a second app that you then try to get the value from. You need to get from the exact same object:
var express = require('express');
var app = express();
app.set('foo', 'bar');
app.get('foo');
If you are new to express, you can use the cli generator to scaffold out an application that shows you a sane pattern how to use the same express instance throughout your whole application.

Express 4 Routes Using Socket.io

Having a rough time adding Socket.io in my Express 4 Routes. In my routes/index.js I have:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function (req, res, next) {
res.render('index', { title: 'Express' });
});
router.post('/message', function(req, res) {
console.log("Post request hit.");
// res.contentType('text/xml');
console.log(appjs);
io.sockets.emit("display text", req);
// res.send('<Response><Sms>'+req.body+'</Sms></Response>');
});
module.exports = router;
but io is undefined. I have seen several examples of how to do this, but none that worked for me. Any help would be appreciated.
You need to pass your socket.io variable to the router module so that it has access. You could do this by wrapping your module in a function call.
var express = require('express');
var router = express.Router();
/* GET home page. */
var returnRouter = function(io) {
router.get('/', function(req, res, next) {
res.render('index', {
title: 'Express'
});
});
router.post('/message', function(req, res) {
console.log("Post request hit.");
// res.contentType('text/xml');
console.log(appjs);
io.sockets.emit("display text", req);
// res.send('<Response><Sms>'+req.body+'</Sms></Response>');
});
return router;
}
module.exports = returnRouter;
Then, whever you import this route you would call this function like: require(./routefile)(io)
Here's a good article about creating modules that require being passed a variable: Node.Js, Require and Exports
How about exploiting events? This could add an extra layer of self-awareness to the app, including socket messaging.
Since express's app() inherits from node's eventEmitter, I app.emit('EVENT_NAME', payload) at any point in my route handlers,
and then just handle that with app.on('EVENT_NAME', function(payload){})
with any logic available. I'm using it in my current setup.
This is super old, but I was looking to do the same thing and didn't find a suitable answer. I came up with a good solution using app.set('socketio', io) and req.app.get('socketio') in my route. I was then able to create a reference to the sender's socket in my route without using io.on().
See the answer I added here for the code:
Use socket.io inside a express routes file

NodeJS/Express app.use sequence and usage

I tried to separate my node routing into two parts: HTML/App and REST. Here is what I've done:
app.js:
var appPort = process.env.PORT || 80;
var express = require('express');
var http = require('http');
var appRouter = require('./routes/index');
var restRouter = require('./routes/rest');
var app = express();
var srv = http.createServer(app);
app.set('port', appPort);
app.set('view engine', 'jade');
app.use(express.static(path.join(__dirname, 'public')));
app.use('/api/rest/', restRouter); // this seems not working .. I never get the expected response
app.use('/', appRouter); // I get this even with localhost/api/rest/...
var server = srv.listen(app.get('port'), function() {
debug('Express server listening ' + server.address().address + ':' + server.address().port);
});
index.js:
var express = require('express');
var router = express.Router();
router.get('/*', function (req, res) {
res.send('HOME')
});
module.exports = router;
rest.js
var express = require('express');
var router = express.Router();
router.get('/api/rest/*', function(req, res) {
res.send('REST API');
});
module.exports = router;
My questions:
1. It's possible in general to build multiple routers in this way?
2. Does the sequence of get.use matter, and/or do I have to deal with 'next'?
3. In case I would like to access a database inside the router can I hand over a parameter like this:
// ...
var client = new pg.Client(dbConnection);
// ...
app.use('/', appRouter(client));
1) It is possible to build multiple routers this way.
Because you are using this:
app.use('/api/rest/', restRouter);
your route calls in rest.js will be relative to /api/rest/ which means your code should be modified in rest.js to look like this:
router.get('*', function(req, res) {
res.send('REST API');
});
I would also encourage you to see the Express multi-router example on GitHub. It illustrates this point very clearly by showing a REST app with versioned routes.
2) The order of things matter
See the Express documentation for app.use and you will note:
Middleware functions are executed sequentially, therefore the order of
middleware inclusion is important.
If you reverse the order of your app.use calls, the router.get('/*', function (req, res) { line in index.js will catch everything before you get to other routes...defeating your purpose.
Also, if you don't call next, Express has no way to know that you are done or even that you want to continue to the next middleware or route.
3) The database question is a modules/scope question
This is more of a scope question than an Express question. I'd suggest looking up some of the excellent writing about javascript scope and also on how Node handles modules.

Categories

Resources